Jail And Container Configuration With Bind Mounts

Defining Bind Mounts

What are bind mounts?

Bind mounts are a mechanism to expose a file or directory on the host system into a chroot jail or Linux container. They allow sharing of configuration files, application code, and data between the host and isolated environments. Bind mounts map a path from the host file system hierarchy into the sandboxed filesystem namespace.

How bind mounts provide separation

Jails and containers provide process, networking, and filesystem isolation from the host system. However, some sharing between environments is often necessary. Bind mounts selectively bridge the gap to provide controlled access for sharing directories and files.

For example, application configuration may be managed on the host but needs to be exposed into containers. Or shared libraries on the host may need mounting into multiple jails. Bind mounts provide this bridge in a secure way.

Bind mount types and use cases

There are two main types of bind mounts:

  • Read-only – Shared directories from host exposed read-only
  • Read-write – Shared directories with read-write access

Read-only bind mounts are generally recommended as they prevent any state from being changed on the host. Some common use cases include:

  • Application code/binaries – Mounted read-only
  • Configuration – Mounted read-only
  • Log directories – Mounted read-write
  • Data directories – Mounted read-write

Configure bind mounts carefully based on the specific sharing needs between host and containers. Favor read-only wherever possible.

Configuring Bind Mounts for Jails

Enabling bind mounts in jail.conf

To use bind mounts in a FreeBSD jail, the admin must first enable the mount capability in the jail configuration. This is done in jail.conf by adding:

mount;
mount.devfs;

The mount capability allows mounting filesystems in general. And mount.devfs specifically allows mounting devfs to expose host devices.

Mounting host directories into jails

With mounting enabled, host directories are exposed via fstab syntax. For example:

/usr/local/www /jails/web/usr/local/www nullfs ro 0 0

This will mount the host’s web root directory into the jail at the same path. The nullfs indicates it is bind mounted versus a discrete filesystem.

Read-only versus read-write mounts

Be default bind mounts are read-only. This prevents the jail from writing to or modifying the host system.

To mount a directory read-write instead, change the mount options to rw like:

/tmp /jails/web/tmp nullfs rw 0 0

This would allow full read-write access on /tmp between the host and jail.

Example jail.conf bind mount configurations

Some common examples include:

# Application code read-only
/usr/local/www /jails/web/usr/local/www nullfs ro 0 0 

# Writable log dir 
/var/log/web /jails/web/var/log nullfs rw 0 0

And for application dependencies:

  
# Binaries
/usr/local/bin /jails/app/usr/local/bin nullfs ro 0 0

# Shared libs
/usr/local/lib /jails/app/usr/local/lib nullfs ro 0 0 

Always validate that the jail starts properly after making bind mount changes before deploying into production.

Leveraging Bind Mounts with Docker and Podman

Dockers built-in bind mount options

Docker natively supports bind mounting host directories into containers using the -v argument. For example:

docker run -v /host/directory:/container/directory image-name

This will expose /host/directory from the host into the container at /container/directory.

Sharing configuration via named volumes

Docker named volumes can also be used for sharing configuration:

docker volume create config
docker run -v config:/container/config image-name

This creates a shared volume that can be mounted into multiple containers.

Read-only bind mounts for application code

Make use of the built-in :ro option to mount directories read-only:

  
docker run -v /host/code:/container/code:ro image-name

This is useful for mounting in shared application code read-only.

Example Podman container launch with bind mounts

Podman supports the same -v bind mount syntax as Docker. For example:

podman run -v /host/config:/container/config:ro -v /host/data:/container/data:rw image-name

This launches a Podman container with the host config directory mounted read-only, and a writable data directory mount.

Securing Bind Mounts Against Container Breakout

Mount namespaces and privilege requirements

There are potential security implications of bind mounts to consider. Containers use mount namespaces to establish independent filesystem views.

Privileged containers are able to mount over directories on the host system to “breakout” of the container namespace. Similar risks exist with read-write bind mounts.

Risks of writable mounts to the host system

If a container vulnerability allows executing code in the context of the container, read-write bind mounts pose further risk.

For example, if /host/logs is mounted into the container read-write an exploit could manipulate host log files. Or inject monitoring tools to gather data from the host system.

Recommendations for read-only mounts only

To limit exposure only mount directories read-only unless write access is absolutely required:

 
docker run -v /host/code:/container/code:ro image-name

This eliminates the possibility of container breakout risk from bind mounts.

Dropping privileges with user namespacing

Additional mitigations include running containers with a non-root user via Docker’s userns-remap option. This adds user namespacing:

docker run --userns=host -u 1000:1000 image-name

User namespaces provide additional privilege separation between the container and host system.

Leave a Reply

Your email address will not be published. Required fields are marked *