Home > Mobile >  Permission denied while executing binaries in tmp folder (Docker)
Permission denied while executing binaries in tmp folder (Docker)

Time:10-29

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.

CodePudding user response:

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.

CodePudding user response:

Complete summary of solution -

@davidmaze mentioned to add an anonymous volume using

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

as I replied I am still getting an error Cannot create temporary file in ./: Read-only file system when I tried to compile my program. When I debugged my container to see file system changes in read_only:false mode, I found that compiler is trying to save the a.out file in /bin folder, which is suppose to be read only.

So I added this additional line before the entry point and my issue was solved.

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

WORKDIR /build <---- this line

ENTRYPOINT [ "worker" ]

  • Related