Search code examples
dockerdocker-composedockerfile

Permission denied while executing binaries in tmp folder (Docker)


Hello I am trying to build an image which can compile and run a c++ program securely.

FROM golang:latest as builder

WORKDIR /app
COPY . .

RUN go mod download
RUN env CGO_ENABLED=0 go build -o /worker

FROM alpine:latest
RUN apk update && apk add --no-cache g++ && apk add --no-cache tzdata
ENV TZ=Asia/Kolkata

WORKDIR /

COPY --from=builder worker /bin

ARG USER=default
RUN addgroup -S $USER && adduser -S $USER -G $USER

USER $USER

ENTRYPOINT [ "worker" ]
version: "3.9"
services:
  gpp:
    build: .
    environment:
      - token=test_token
      - code=#include <iostream>\r\n\r\nusing namespace std;\r\n\r\nint main() {\r\n   int a = 10;\r\n   int b = 20;\r\n   cout << a << \" \" << b << endl;\r\n   int temp = a;\r\n   a = b;\r\n   b = temp;\r\n   cout << a << \" \" << b << endl;\r\n   return 0;\r\n}
    network_mode: bridge
    privileged: false
    read_only: true
    tmpfs: /tmp
    security_opt:
      - "no-new-privileges"
    cap_drop:
      - "all"

Here worker is a golang binary which reads code from environment variable and stores it in /tmp folder as main.cpp, and then tries to compile and run it using g++ /tmp/main.cpp && ./tmp/a.out (using golang exec)

I am getting this error scratch_4-gpp-1 | Error : fork/exec /tmp/a.out: permission denied, from which what I can understand / know that executing anything from tmp directory is restricted.

Since, I am using read_only root file system, I can only work on tmp directory, Please guide me how I can achieve above task keeping my container secured.


Solution

  • Docker's default options for a tmpfs include noexec. docker run --tmpfs allows an extended set of mount options, but neither Compose tmpfs: nor the extended syntax of volumes: allows changing anything other than the size option.

    One straightforward option here is to use an anonymous volume. Syntactically this looks like a normal volumes: line, except it only has a container path. The read_only: option will make the container's root filesystem be read-only, but volumes are exempted from this.

    version: '3.8'
    services:
      ...
        read_only: true
        volumes:
          - /build # which will be read-write
    

    This will be a "normal" Docker volume, so it will be disk-backed and you'll be able to see it in docker volume ls.