Skip to content

Use systemd directive OpenFile= to let Podman inherit a Unix socket

License

Notifications You must be signed in to change notification settings

eriksjolund/podman-OpenFile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 

Repository files navigation

podman-OpenFile

Demo: Use systemd directive OpenFile= to let Podman inherit an already connected Unix socket.

The systemd directive OpenFile= was introduced in systemd 253 (released 15 February 2023).

Problem: A container process does not have file permissions to access a UNIX socket.

Solution: Start the container via systemd-run --property OpenFile=... ... so that systemd connects to the UNIX socket. The container process inherits the established socket.

For example, OpenFile= makes it possible to fetch a web page with libcurl in a container, even when the container user does not have enough file permission to access the UNIX socket of the web server. It works because systemd will connect to the UNIX socket and then let Podman inherit the file descriptor of the established socket. The container process inherits the same file descriptor.

stateDiagram-v2
    systemd: systemd connects to UNIX socket (specified by OpenFile=)
    systemd --> podman: socket inherited via fork/exec
    state "OCI runtime" as s2
    podman --> conmon: socket inherited via double fork/exec
    conmon --> s2: socket inherited via fork/exec
    s2 --> container: socket inherited via exec
Loading

Test 3 gives a demonstration of this.

Requirements

  • systemd 253

  • podman

You could for instance use Fedora 38 or later. An easy way to try it out is to use Fedora CoreOS (stream = next) which already contains Fedora 38.

Run a web server that listens on a Unix socket

  1. Create the file ~/Caddyfile with the file contents
    { 
    }
    
    http://localhost {
      bind unix//sockdir/sock
      respond "Hello world
    "
    }
    
  2. Run
    mkdir ~/sockdir
    
  3. Run
    podman run \
     --detach \
     --name caddy \
     --replace \
     --rm \
         -v ~/Caddyfile:/etc/caddy/Caddyfile:Z \
         -v ~/sockdir:/sockdir:Z \
       docker.io/library/caddy
    
    The command creates the Unix socket ~/sockdir/sock that has the file permissions 755.

Test 1: fetch a web page as container user root (Success)

Fetch a web page with curl (running as the container user root)

podman run \
       --rm \
       -v ~/sockdir:/sockdir:Z \
       registry.fedoraproject.org/fedora \
	 curl \
	   --no-progress-meter \
	   --unix-socket /sockdir/sock \
           http://localhost

The command outputs

Hello world

and exits successfully.

Test 2: fetch a web page as container user nobody (Failure)

Fetch a web page with curl (running as the container user nobody (UID 65534 and GID 65534).

podman run \
       --rm \
       --user 65534:65534 \
       -v ~/sockdir:/sockdir:Z \
	  registry.fedoraproject.org/fedora \
	    curl \
	      --no-progress-meter \
	      --unix-socket /sockdir/sock \
	      http://localhost

The command fails with the error message

curl: (7) Couldn't connect to server

The UNIX socket ~/sockdir/sock has file permissions 755. The user nobody inside the container, thus only has Read (4) and Execute (1) permissions.

The error

curl: (7) Couldn't connect to server

can be avoided if we set less restrictive file permissions, for example by running chmod 777 ~/sockdir/sock.

Is there a way to download the web page as the container user nobody without changing the file permissions of the Unix socket? Yes, by using the systemd directive OpenFile= (see Test 3).

Test 3: Use OpenFile= and fetch a web page as container user nobody (Success)

The curl example program externalsocket.c demonstrates how libcurl can use an already established socket when accessing a web server.

The file externalsocket.c was adapted to make use of a UNIX socket file descriptor that originates from OpenFile=

  1. Build a container from the modified externalsocket.c
    git clone https://github.com/eriksjolund/curl.git
    cd curl
    git switch externalsocket_openfile
    podman build -t demo docs/examples
    
  2. Fetch the web page as container user nobody
    systemd-run \
      --quiet \
      --property OpenFile=$HOME/sockdir/sock:fdnametest \
      --user \
      --collect \
      --pipe \
      --wait \
      podman \
        run \
        --rm \
        --user 65534:65534 \
        localhost/demo fdnametest http://localhost
    
    The command outputs:
    Hello world
    
    and exits successfully.

About

Use systemd directive OpenFile= to let Podman inherit a Unix socket

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published