Passthrought USB TV tuner (DVB RTL2838) to unprivileged container inside Debian Bullseye host

esp13

New Member
Jun 14, 2022
1
0
1
Hi, I have some question about using VDR inside a lxc container. I'm not sure if here is the right place to ask, but as I found some usefull related indications (https://forum.proxmox.com/threads/r...le-as-ads-b-receiver-in-lxc-container.103378/ https://forum.proxmox.com/threads/lxc-usb-webcam-passthrough.107309/ https://forum.proxmox.com/threads/usb-passthrough-auf-unprivilegierten-lxc-container.93540/ for examples) I give a try. Feel free to ask me to leave if this is the wrong place.

I’m using lxc on a Debian Bullseye server.
I run all my containers (Debian Bullseye ones too) unprivileged with the lxc-unpriv-start command.

I’m trying to use a USB DVB TV tuner (RTL2838) inside my lxc container.
So I have to do some USB passthrough

on host:
lsusb
returns my USB DVB adapter:
Bus 001 Device 003: ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 DVB-T

ls -l /dev/bus/usb/001
returns:
Code:
total 0
crw-rw-r-- 1 root root 189, 0 16 mai   21:25 001
crw-rw-r-- 1 root root 189, 1 16 mai   21:25 002
crw-rw-r-- 1 root root 189, 2 16 mai 21:25 003

ls -l /dev/dvb
returns:
Code:
total 0
drwxr-xr-x 2 root root 120 16 mai   21:25 adapter0

ls -l /dev/dvb/adapter0
returns:
Code:
total 0
crw-rw----+ 1 root video 212, 0 16 mai   21:25 demux0
crw-rw----+ 1 root video 212, 1 16 mai   21:25 dvr0
crw-rw----+ 1 root video 212, 3 16 mai   21:25 frontend0
crw-rw----+ 1 root video 212, 2 16 mai 21:25 net0

On the host as non root user:
nano /home/mynonrootusername/.local/share/lxc/mycontainername/config
is set this way:
Code:
lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/userns.conf
lxc.arch = linux64
lxc.include = /etc/lxc/default.conf
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.apparmor.profile = unconfined
lxc.rootfs.path = dir:/home/mynonrootusername/.local/share/lxc/mycontainername/rootfs
lxc.uts.name = mycontainername
lxc.cgroup2.devices.allow = c 189:* rwm
lxc.mount.entry = /dev/bus/usb/001 dev/bus/usb/001 none bind,optional,create=dir
lxc.cgroup2.devices.allow = c 212:* rwm
lxc.mount.entry = /dev/dvb/adapter0 dev/dvb/adapter0 none bind,optional,create=dir

On the host as root user:
nano /etc/lxc/default.conf
Is set this way:
Code:
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.apparmor.profile = generated

On the host as nonroot user I start my container like this:
lxc-unpriv-start -n mycontainername
lxc-unpriv-attach -n mycontainername
(Please care of the use of -unpriv part)

Inside the container as non root user:
ls -la /dev/bus/usb/001
returns
Code:
total 0
drwxr-xr-x 2 nobody nogroup    100 May 16 19:25 .
drwxr-xr-x 3 root   root        60 May 16 20:36 …
crw-rw-r-- 1 nobody nogroup 189, 0 May 16 19:25 001
crw-rw-r-- 1 nobody nogroup 189, 1 May 16 19:25 002
crw-rw-r-- 1 nobody nogroup 189, 2 May 16 19:25 003

and

ls -la /dev/dvb
returns
Code:
total 0
drwxr-xr-x 3 root   root     60 May 16 20:36 .
drwxr-xr-x 7 root   root    540 May 16 20:36 …
drwxr-xr-x 2 nobody nogroup 120 May 16 19:25 adapter0

and

ls -la /dev/dvb/adapter0
returns
Code:
total 0
drwxr-xr-x  2 nobody nogroup    120 May 16 19:25 .
drwxr-xr-x  3 root   root        60 May 16 20:36 …
crw-rw----+ 1 nobody nogroup 212, 0 May 16 19:25 demux0
crw-rw----+ 1 nobody nogroup 212, 1 May 16 19:25 dvr0
crw-rw----+ 1 nobody nogroup 212, 3 May 16 19:25 frontend0
crw-rw----+ 1 nobody nogroup 212, 2 May 16 19:25 net0

So at this point there are some permission issues (nobody / nogroup shouldn't display here I think)

So when I launch vdr inside container as non root user:
vdr
I get
vdr: no primary device found - using first device!

What am I missing?

On the test computer (outside of any lxc container) I can run vdr without root rights as normal user and it could successfully run/drive the dvb adapter.
I guess it is because of /dev/dvb/adapter0 being part of group “video” too? (see above)

I guess I should do something with the host video group.
As non root user on host :
id
uid=1000(mynonrootuser) gid=1000(mynonrootuser) groupes=1000(mynonrootuser),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)

I should maybe modify the mapping, I tried to map the video group:
Code:
lxc.idmap = u 0 100000 65535
lxc.idmap = g 0 100000 44
lxc.idmap = g 44 44 1
lxc.idmap = g 45 100045 65490

But then my lxc container doesn't start anymore:
tools/lxc_start.c: main: 308 The container failed to start

Code:
confile - confile.c:set_config_idmaps:1942 - Read uid map: type u nsid 0 hostid 100000 range 65536
confile - confile.c:set_config_idmaps:1942 - Read uid map: type g nsid 0 hostid 100000 range 44
confile - confile.c:set_config_idmaps:1942 - Read uid map: type g nsid 44 hostid 44 range 1
confile - confile.c:set_config_idmaps:1942 - Read uid map: type g nsid 45 hostid 100045 range 65491
lxccontainer - lxccontainer.c:do_lxcapi_start:979 - Set process title to [lxc monitor] /home/mynonrootuser/.local/share/lxc mycontainername
lxccontainer - lxccontainer.c:wait_on_daemonized_start:840 - First child 5080 exited
apparmor - lsm/apparmor.c:lsm_apparmor_ops_init:1269 - Per-container AppArmor profiles are disabled because the mac_admin capability is missing
lsm - lsm/lsm.c:lsm_init:40 - Initialized LSM security driver AppArmor
conf - conf.c:add_idmap_entry:4462 - Adding id map: type u nsid 0 hostid 100000 range 1
conf - conf.c:add_idmap_entry:4462 - Adding id map: type u nsid 1000 hostid 1000 range 1
conf - conf.c:add_idmap_entry:4462 - Adding id map: type g nsid 0 hostid 100000 range 1
conf - conf.c:add_idmap_entry:4462 - Adding id map: type g nsid 1000 hostid 1000 range 1
conf - conf.c:add_idmap_entry:4462 - Adding id map: type g nsid 5 hostid 100005 range 1
conf - conf.c:idmaptool_on_path_and_privileged:2728 - The binary "/usr/bin/newuidmap" does have the setuid bit set
conf - conf.c:idmaptool_on_path_and_privileged:2728 - The binary "/usr/bin/newgidmap" does have the setuid bit set
conf - conf.c:lxc_map_ids:2796 - Functional newuidmap and newgidmap binary found
utils - utils.c:lxc_switch_uid_gid:1398 - Switched to gid 0
utils - utils.c:lxc_switch_uid_gid:1407 - Switched to uid 0
utils - utils.c:lxc_setgroups:1420 - Dropped additional groups
terminal - terminal.c:lxc_terminal_peer_default:672 - Using terminal "/dev/null" as proxy
terminal - terminal.c:lxc_terminal_peer_default:675 - File descriptor for "/dev/null" does not refer to a terminal
terminal - terminal.c:lxc_terminal_create_foreign:901 - Failed to allocate proxy terminal
start - start.c:lxc_init:813 - Failed to create console
start - start.c:__lxc_start:1945 - Failed to initialize container "mycontainername"
conf - conf.c:run_script_argv:330 - Executing script "/usr/share/lxcfs/lxc.reboot.hook" for container "mycontainername", config section "lxc"
lxccontainer - lxccontainer.c:wait_on_daemonized_start:851 - No such file or directory - Failed to receive the container state
lxc_start - tools/lxc_start.c:main:308 - The container failed to start
lxc_start - tools/lxc_start.c:main:311 - To get more details, run the container in foreground mode
lxc_start - tools/lxc_start.c:main:313 - Additional information can be obtained by setting the --logfile and --logpriority options

Do you think there is a way to make this working, what could I be missing?
Is it because I’m trying to get my containers having different idmap rules?
Should I use the security.idmap.isolated=true variable somehow?
Maybe on the host I should modify the file to add the “video” group line in /etc/subgid file?:
nano /etc/subuid
myusername:100000:65536

nano /etc/subgid
myusername:100000:65536 video:44:1
 
This is what I did to get my two PlayStation PlayTV DVB-T tuners working for my MythTV Backend container. Container in this example is built on Ubuntu 22.04 and the host is running PVE 7.2.7:

Create your container as normal.

On the HOST (not the container), get the list of USB devices. The two PlayTV tuners are the SCEH-0036 devices:

Code:
root@proxmox:~# lsusb
Bus 002 Device 003: ID 1415:0003 Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc. SCEH-0036
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 006: ID 0624:0249 Avocent Corp. Virtual Keyboard/Mouse
Bus 001 Device 005: ID 413c:a001 Dell Computer Corp. Hub
Bus 001 Device 004: ID 1415:0003 Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc. SCEH-0036
Bus 001 Device 003: ID 0557:2221 ATEN International Co., Ltd Winbond Hermon
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
root@proxmox:~#

Lookup the DVB-T device and record the major number (we only need to lookup the first adapter as they are all the same. Major is 212 in this case - note that I have four adapters visible because the PlayTV is a single USB device but with two physical tuners inside, so two devices is four tuners):

Code:
root@proxmox:~# ls -l /dev/dvb
total 0
drwxr-xr-x 2 root video 120 Jul 28 09:15 adapter0
drwxr-xr-x 2 root video 120 Jul 28 09:15 adapter1
drwxr-xr-x 2 root video 120 Jul 28 09:15 adapter2
drwxr-xr-x 2 root video 120 Jul 28 09:15 adapter3
root@proxmox:~# ls -l /dev/dvb/adapter0
total 0
crw-rw---- 1 root video 212, 0 Jul 28 09:15 demux0
crw-rw---- 1 root video 212, 1 Jul 28 09:15 dvr0
crw-rw---- 1 root video 212, 3 Jul 28 09:15 frontend0
crw-rw---- 1 root video 212, 2 Jul 28 09:15 net0
root@proxmox:~#

Now ensure your container is shutdown and then edit the configuration for your container:

Code:
root@proxmox:~# nano /etc/pve/lxc/CONTAINERNUMBER.conf

Add the following lines to the end of the configuration, specifying the major number in the first line:

Code:
lxc.cgroup2.devices.allow: c 212:* rwm
lxc.mount.entry: /dev/dvb dev/dvb none bind,optional,create=dir

Save and exit your text editor (CTRL+X, then Y then Enter if you are using nano).

Now we have to change the owner and group of the DVB devices on the host so the container can use them. Since the original setup has the DVB-T devices owned by user "root" and group "video", we set the root uid (0 to 100000) and video gid (44 to 100044) accordingly:

Code:
root@proxmox:~# chown 100000:100044 -R /dev/dvb
root@proxmox:~#

Now start your container and, in my case, install the MythTV backend and start scanning for channels.

The only downside to this approach is that the change of owner and group on the /dev/dvb folder does not survive a reboot of the host. You need to apply this again before you start your container (or just restart your DVB application after you've changed done the chown command on the host).

I just need to come up with the appropriate lxc.idmap configuration to make this complete. Previous examples in other threads don't seem to work for me - the container simply fails to start up.
 
  • Like
Reactions: leesteken
So sadly that didn't work for me either - the container still fails to start, but I found a very good workaround.

I have a bash script to set the correct owner, and then just scheduled the root cron to execute it on an @reboot schedule. Works a treat, and I can reboot with confidence knowing that the MythTV container can use the tuners right away without any further intervention.

Code:
root@proxmox:~# cat SetDVBOwner.sh
#!/bin/bash
chown 100000:100044 -R /dev/dvb
root@proxmox:~#

Then set the cron:

Code:
root@proxmox:~# crontab -l
# Set the owner and group of the DVB-T devices upon reboot so the MythTV container can access them.
@reboot /usr/bin/bash /root/SetDVBOwner.sh
root@proxmox:~#
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!