First setup an unprivileged Ubuntu container with Plex Media Server installed. Inside the container take note of the id of the plex
group.
# Your Plex group's ID may be different
$ getent group plex | cut -d : -f3
998
Shutdown the container for now while we update its configuration. The /dev/dri/renderD128 is the device responsible for the Intel QuickSync VAAPI for hardware video encoding. Listing the /dev/dri directory you will see something like this:
$ ls -la /dev/dri
drwxr-xr-x 3 root root 100 Jul 10 19:23 .
drwxr-xr-x 22 root root 4.4K Jul 16 23:57 ..
drwxr-xr-x 2 root root 80 Jul 10 19:23 by-path
crw-rw---- 1 root video 226, 0 Jul 10 19:23 card0
crw-rw---- 1 root render 226, 128 Jul 10 19:23 renderD128
Take note that the renderD128 device is a character device denoted by the 'c' at the beginning of its permission attributes. The devices major and minor numbers are 226, 128 respectively, and is accessible by the render
group. Take note of the render
group's id as well.
# Again your render group ID may be different
$ getent group render | cut -d : -f3
108
Open the container's configuration file. Within a Proxmox installation it will be located in /etc/pve/lxc
and have a name corresponding to the container's assigned ID.
Append the following to the configuration:
# Allow the container access to the renderD128 device identified by its type and major/minor numbers.
# The attributes 'rwm' allow the container to perform read, write and mknod operations on the device.
#
# For Proxmox 6.x (LXC 3.x):
lxc.cgroup.devices.allow: c 226:128 rwm
#
# For Proxmox 7.x (LXC 4.x uses CGroupV2):
lxc.cgroup2.devices.allow: c 226:128 rwm
# Bind mount the device from the host to the container
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file 0 0
At this point, if the container were running, the device would be visible in the container but belong to the user and group nobody
and nogroup
respectively. The Plex user would not be able to write to it.
LXC helps isolate containers by mapping a set of user and group ids on the host to a set of user and group ids in the container. Normally a set of ids outside the POSIX range of 0-65535 is used on the host to map container user and groups. By default, Proxmox has LXC configured to map host user and groups 100000-165535 to container user and groups 0-65535. In the event of a container escape exploit, the malicious user from the container would not have permissions to modify the host filesystem.
So now its clear that the render
group (108) on the host does not fall within the range mapped to the container. This is why the device is mounted with nobody/nogroup. We can update the container configuration further to use a custom id mapping that will map the plex
group in the container (998) to the render
group on the host (108).
# /etc/pve/lxc/CONTAINER_ID.conf
# In older versions of LXC, the configuration was lxc.id_map
# Syntax:
# Column 1: u/g define map for user or group ids
# Column 2: Range start for container
# Column 3: Range start for host
# Column 4: Length of range
# i.e., g 0 100000 998 = Map gids 100000-100997 on host to 0-997 in container
lxc.idmap: u 0 100000 65536
lxc.idmap: g 0 100000 998
lxc.idmap: g 998 108 1
lxc.idmap: g 999 100999 64537
The key is to define a jump in the mapping that has only one group overlapping with the host range (render
<-> plex
).
Finally, we have to update the /etc/subgid
file to allow us to apply this custom mapping. The subuid/subgid files define which id mappings a host user can make while using LXC. The first column is the host user, the second column is the start of the host id range to be mapped, and the third column is the number of ids that can be allocated.
# /etc/subgid
root:100000:65536
root:108:1 # Add this line
Files on the host filesystem that are accessible by the render
group could now be modified in the event of a container escape vulnerability. Few files belong to that group and this configuration is much more constrained than a privileged container, so I am comfortable with this level of risk. Make sure you understand the potential consequences before mapping container uid/gids into the commonly-used range of host ids.
@packerdl
/etc/pve/lxc/200.conf
arch: amd64 cores: 2 features: mount=cifs hostname: plex memory: 4096 net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=52:33:97:41:CD:D0,ip=dhcp,type=veth onboot: 0 ostype: debian rootfs: local-lvm:vm-200-disk-0,size=208G swap: 4096 lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file lxc.idmap: u 0 100000 65536 lxc.idmap: g 0 100000 998 lxc.idmap: g 998 103 1 lxc.idmap: g 999 100999 64537
/etc/subgid
root:100000:65536 root:103:1
/etc/subuid
root:100000:65536