Skip to content

Instantly share code, notes, and snippets.

@Underknowledge
Last active September 11, 2024 11:38
Show Gist options
  • Save Underknowledge/78bdf079469f3f5eb4d1dfb9419cc149 to your computer and use it in GitHub Desktop.
Save Underknowledge/78bdf079469f3f5eb4d1dfb9419cc149 to your computer and use it in GitHub Desktop.
Install and sign v4l2loopback in fedora
#!/usr/bin/env bash
# set -x
Git_status=$(curl --silent -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/umlaeute/v4l2loopback/tags" )
TAR_dl=$( echo "${Git_status}" | jq -r ".[].tarball_url" | head -n1)
TAR_v=$( echo "${Git_status}" | jq -r ".[].name" | head -n1)
build_dir="${build_dir:-/usr/src/v4l2loopback-"${TAR_v}"}"
tmp_dir="${tmp_dir:-/tmp}"
mokutil_out_dir="${mokutil_out_dir:-/root/.ssh/mokutil-module-signing}"
mokutil_509key_pass=$(cat "${mokutil_out_dir}"/.openssl_pass)
mokutil_509key_pass="${mokutil_509key_pass:-$(openssl rand -hex 6)}"
# https://github.com/umlaeute/v4l2loopback/issues/394
# https://unix.stackexchange.com/questions/445772/how-to-add-a-public-key-into-system-keyring-for-kernel-without-recompile
# https://docs.fedoraproject.org/en-US/fedora/rawhide/system-administrators-guide/kernel-module-driver-configuration/Working_with_Kernel_Modules/#sect-signing-kernel-modules-for-secure-boot
# ToDo:
# - Maybe systemd service, needs testing
source /etc/os-release || source /usr/lib/os-release
case ${ID,,} in
*suse*) pkg_mgr_cmd="zypper -n in"; sign_file_dir="/usr/src/linux-obj/x86_64/default/scripts" ;;
centos|rhel|fedora) pkg_mgr_cmd="dnf install -y"; pkg_check_cmd="rpm -qa" ;;
ubuntu|debian) pkg_mgr_cmd="apt-get install -y"; pkg_check_cmd="dpkg-query -l" ;;
# Gentoo needs to have version set since it's rolling
gentoo) pkg_mgr_cmd="emerge --jobs=4"; export VERSION="rolling" ;;
*) warn "unsupported distribution: ${ID,,}" ;;
esac
function info { echo -e "\e[32m[info] $*\e[39m"; }
function warn { echo -e "\e[33m[warn] $*\e[39m"; }
function error { echo -e "\e[31m[error] $*\e[39m"; exit 1; }
function check_install { ${pkg_check_cmd} "$*" | grep -q "$*" || ( ${pkg_mgr_cmd} "$*"; warn "you probably have to reboot" ; false ); }
check_install kernel-headers
check_install kernel-devel
command -v openssl > /dev/null 2>&1 || ( warn "missing openssl"; ${pkg_mgr_cmd} openssl )
command -v jq > /dev/null 2>&1 || ( warn "missing jq"; ${pkg_mgr_cmd} jq )
command -v curl > /dev/null 2>&1 || ( warn "missing curl"; ${pkg_mgr_cmd} curl )
command -v mokutil > /dev/null 2>&1 || ( warn "missing mokutil" ; ${pkg_mgr_cmd} mokutil )
function check_key () {
if [ -f "${mokutil_out_dir}"/MOK.priv ]; then
info "probing MOK.der"
if mokutil --test-key "${mokutil_out_dir}/MOK.der" | grep -q "already enrolled"; then
info "The Key is already trusted"
install_v4l2loopback
else
warn "info the key exist but is not trusted yet, reimporting it because it does not hurt. You missing a reboot?"
import_trust
fi
else
info "Generating keys to sign"
mokutil_setup
fi
}
function signing_ko () {
export KBUILD_SIGN_PIN="${mokutil_509key_pass}"
sign_file_dir="${sign_file_dir:-/usr/src/kernels/"$(uname -r)"/scripts}"
if [[ -f /lib/modules/"$(uname -r)"/extra/v4l2loopback.ko.xz || -f /lib/modules/"$(uname -r)"/extra/v4l2loopback.ko ]]; then
ko_folder="${ko_folder:-/lib/modules/$(uname -r)/extra}"
elif [[ -f /lib/modules/"$(uname -r)"/extra/v4l2loopback/v4l2loopback.ko.xz || -f /lib/modules/"$(uname -r)"/extra/v4l2loopback/v4l2loopback.ko ]]; then
ko_folder="${ko_folder:-/lib/modules/$(uname -r)/extra/v4l2loopback}"
else
warn "Can not locate the folder used for v4l2loopback.ko.xz to unxz and sign. Find the file and try to set the var 'ko_folder'"
fi
if [[ ! -f "${ko_folder}"/v4l2loopback.ko.xz || ! -f "${ko_folder}"/v4l2loopback.ko ]]; then
warn "there might be no file to sign. Please check ${ko_folder}" ; ko_folder="${ko_folder:-/lib/modules/$(uname -r)/extra}"
fi
info "Cert Password:"
info "$mokutil_509key_pass"
unxz -f "${ko_folder}/v4l2loopback.ko.xz"
${sign_file_dir}/sign-file sha256 "${mokutil_out_dir}/MOK.priv" "${mokutil_out_dir}/MOK.der" "${build_dir}/v4l2loopback.ko" && info "${build_dir}/v4l2loopback.ko"
${sign_file_dir}/sign-file sha256 "${mokutil_out_dir}/MOK.priv" "${mokutil_out_dir}/MOK.der" "${ko_folder}/v4l2loopback.ko" && info "${ko_folder}/v4l2loopback.ko"
xz -f "${ko_folder}/v4l2loopback.ko"
info "finished signing_ko"
}
function mokutil_setup () {
if [ ! -f "${mokutil_out_dir}"/MOK.priv ]; then
info "Still no Private key found, Generating one"
( umask 077 && mkdir -p "${mokutil_out_dir}")
name="$(hostname)_signing_key"
echo "${mokutil_509key_pass}" > "${mokutil_out_dir}/.openssl_pass"
openssl \
req -new -x509 \
-passin pass:"${mokutil_509key_pass}" \
-passout pass:"${mokutil_509key_pass}" \
-newkey rsa:2048 \
-keyout "${mokutil_out_dir}/MOK.priv" \
-outform DER \
-out "${mokutil_out_dir}/MOK.der" \
-days 31500 \
-subj "/CN=${name}/" \
-addext "extendedKeyUsage=codeSigning" || error "issue creating cert"
openssl x509 -inform der -in "${mokutil_out_dir}"/MOK.der -out "${mokutil_out_dir}"/MOK.pem
mkdir -p /usr/src/kernels/"$(uname -r)"/certs/
cat "${mokutil_out_dir}"/MOK.pem > /usr/src/kernels/"$(uname -r)"/certs/signing_key.pem
# cp "${mokutil_out_dir}"/MOK.der /usr/src/kernels/"$(uname -r)"/certs/signing_key.pem
chmod 600 "${mokutil_out_dir}"/MOK*
chmod 600 "${mokutil_out_dir}"/.openssl_pass
echo "The pasword for the x509 cert is: ${mokutil_509key_pass}"
import_trust
else
echo "Private key already present"
fi
info "finished mokutil_setup"
}
function import_trust () {
info "Enroling new cert"
warn "Set a one-time import password, Make it memorablel, you have to type it into later"
warn "for a example check https://gist.github.com/reillysiemens/ac6bea1e6c7684d62f544bd79b2182a4"
mokutil --import "${mokutil_out_dir}"/MOK.der
info "A Key has been generated and importet into mokutil"
mokutil --list-new
info "Now reboot your machine and import the certificate with the just typed password"
exit 0
info "finished import_trust"
}
function install_v4l2loopback () {
info "start install_v4l2loopback"
curl -SL "${TAR_dl}" -o "${tmp_dir}"/v4l2loopback_"${TAR_v}".tar.gz
mkdir -p "${build_dir}"
tar xfv "${tmp_dir}"/v4l2loopback_"${TAR_v}".tar.gz --directory="${build_dir}"
mv "${build_dir}"/umlaeute-v4l2loopback-*/* "${build_dir}"/.
rm -r "${build_dir}"/umlaeute-v4l2loopback-*
pushd "${build_dir}" || exit
make clean
make || build_failed
mkdir -p /usr/src/kernels/"$(uname -r)"/certs/
if [[ -z "$skip_signing" ]]; then
info "Cert Password:"
info "$mokutil_509key_pass"
export KBUILD_SIGN_PIN="${mokutil_509key_pass}"
cp "${mokutil_out_dir}"/MOK.pem /usr/src/kernels/"$(uname -r)"/certs/signing_key.pem
chmod 444 /usr/src/kernels/"$(uname -r)"/certs/signing_key.pem
# info "stat file"
# stat /usr/src/kernels/"$(uname -r)"/certs/signing_key.pem
fi
make install
ls /lib/modules/"$(uname -r)"/extra/
if [[ -z "$skip_signing" ]]; then
info "Now Manually singing"
signing_ko
fi
popd || return
depmod -a
modprobe v4l2loopback
modinfo v4l2loopback
info "finished install_v4l2loopback"
lsmod | grep -q v4l2loopback && info "v4l2loopback loaded!"
}
function slr_as_webcam () {
# https://medium.com/nerdery/dslr-webcam-setup-for-linux-9b6d1b79ae22
command -v ffmpeg > /dev/null 2>&1 || ( warn "missing ffmpeg"; ${pkg_mgr_cmd} ffmpeg )
command -v gphoto2 > /dev/null 2>&1 || ( warn "missing gphoto2" ; ${pkg_mgr_cmd} gphoto2 )
# Best formats
# https://stackoverflow.com/a/59574988
warn "quick 5s test"
timeout 5 gphoto2 --stdout --capture-movie | ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 "$(v4l2-ctl --list-devices | grep v4l2loopback -A 1 | grep -oe "/dev/video.*" | head -n 1)"
# https://github.com/umlaeute/v4l2loopback/issues/391#issuecomment-800941494
echo "v4l2loopback" > /etc/modules-load.d/v4l2loopback.conf
cat << EOF > /etc/modprobe.d/v4l2loopback.conf
# Module options for v4l2loopback
options v4l2loopback exclusive_caps=1,1
options v4l2loopback devices=2
options v4l2loopback max_buffers=2
options v4l2loopback video_nr=63,102
options v4l2loopback card_label="obs,slr"
EOF
info "Config to Automaticaly load Kernel module added"
}
function build_failed () {
echo "
When you see
*** No rule to make target 'clean'. Stop.
Probably kernel-headers and kernel do not have the same version… Install, reboot and try again!
otherwise you could try running 'dnf donwgrade gcc' https://ask.fedoraproject.org/t/fedora-34-beta-and-oot-kmod-nvidia-virtualbox-v4l2loopback-etc/12778
"
}
function help () {
echo "
just run the script, reboot (you will have to type a pass you set) and run again!
you can also run '$0 slr_as_webcam' to install tools you need to use a dslr as webcam
"
}
if [ "$EUID" -ne 0 ]
then error "Please run as root"
else
if [ "$#" -eq "1" ]
then
$1
exit 0
else
if mokutil --sb-state | grep -q "SecureBoot enabled"; then
grep -q "v4l2loopback" /proc/modules && info "v4l2loopback is loaded" || ( info "Secure boot is enabled and you have to setup singing" ; check_key)
else
warn "no need to sing Stuff!"
export skip_signing=1
grep -q "v4l2loopback" /proc/modules || install_v4l2loopback
fi
fi
fi
@Underknowledge
Copy link
Author

Underknowledge commented Sep 3, 2022

@domrany64 Well, this is not a repo, it is just a gist, but you're right. should move this to one.
More or less just execute it.
The script checks for certain stuff (Is the module loaded, secure-boot enabled, is there a key, generated from the script and so on) and then does things in the right order.

  • first run it, it will prompt you to do a reboot and enrol the key.
  • After a reboot run it again, it will install the module
  • then optional, run the script with the argument slr_as_webcam when you want to have the module automatically loaded and have 2 devices to be used with OBS.
    Whenever you installed a newer kernel version, you have to rerun the script.

@Boffice
Copy link

Boffice commented Sep 4, 2022

Hello,
I am running Fedora 36 on Surface-Linux kernel.

uname -r 5.17.12-1.surface.fc36.x86_64
ls /lib/modules/$(uname -r)

bls.conf config kernel modules.alias.bin modules.builtin.alias.bin modules.builtin.modinfo modules.dep.bin modules.order modules.symbols source vmlinuz build extra modules.alias modules.builtin modules.builtin.bin modules.dep modules.devname modules.softdep modules.symbols.bin System.map

ls /lib/modules/$(uname -r)/extra v4l2loopback

Error while running modprobe - modprobe: ERROR: could not insert 'v4l2loopback': Key was rejected by service

Error While Installation:

/usr/src/v4l2loopback-v0.12.7 /home/boffice/tmp/cam rm -f *~ rm -f Module.symvers Module.markers modules.order make -C /lib/modules/uname -r/build M=/usr/src/v4l2loopback-v0.12.7 clean make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64' make[1]: *** No rule to make target 'clean'. Stop. make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64' make: *** [Makefile:63: clean] Error 2 Building v4l2-loopback driver... make -C /lib/modules/uname -r`/build M=/usr/src/v4l2loopback-v0.12.7 modules
make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make[1]: *** No rule to make target 'modules'. Stop.
make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'```
make: *** [Makefile:43: v4l2loopback.ko] Error 2

When you see 
  *** No rule to make target 'clean'.  Stop. 
Probably kernel-headers and kernel do not have the same version… Install, reboot and try again!
otherwise you could try running 'dnf donwgrade gcc' https://ask.fedoraproject.org/t/fedora-34-beta-and-oot-kmod-nvidia-virtualbox-v4l2loopback-etc/12778

[info] Cert Password:
[info] 8c2c882e4c6e
make -C /lib/modules/uname -r/build M=/usr/src/v4l2loopback-v0.12.7 modules_install
make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make[1]: *** No rule to make target 'modules_install'. Stop.
make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make: *** [Makefile:47: install] Error 2
v4l2loopback
[info] Now Manually singing
[warn] there might be no file to sign. Please check /lib/modules/5.17.12-1.surface.fc36.x86_64/extra/v4l2loopback
[info] Cert Password:
[info] 8c2c882e4c6e
./key.sh: line 74: /usr/src/kernels/5.17.12-1.surface.fc36.x86_64/scripts/sign-file: No such file or directory
./key.sh: line 75: /usr/src/kernels/5.17.12-1.surface.fc36.x86_64/scripts/sign-file: No such file or directory
[info] finished signing_ko
/home/boffice/tmp/cam
modprobe: ERROR: could not insert 'v4l2loopback': Key was rejected by service
filename: /lib/modules/5.17.12-1.surface.fc36.x86_64/extra/v4l2loopback/v4l2loopback.ko.xz
license: GPL
author: Vasily Levin, IOhannes m zmoelnig [email protected],Stefan Diewald,Anton Novikovet al.
description: V4L2 loopback video device
rhelversion: 9.99
depends: videodev
retpoline: Y
name: v4l2loopback
vermagic: 5.17.12-1.surface.fc36.x86_64 SMP preempt mod_unload
parm: debug:debugging level (higher values == more verbose) (int)
parm: max_buffers:how many buffers should be allocated (int)
parm: max_openers:how many users can open loopback device (int)
parm: devices:how many devices should be created (int)
parm: video_nr:video device numbers (-1=auto, 0=/dev/video0, etc.) (array of int)
parm: card_label:card labels for every device (array of charp)
parm: exclusive_caps:whether to announce OUTPUT/CAPTURE capabilities exclusively or not (array of bool)
parm: max_width:maximum frame width (int)
parm: max_height:maximum frame height (int)

@2ndBillGates
Copy link

Hello, I am running Fedora 36 on Surface-Linux kernel.

uname -r 5.17.12-1.surface.fc36.x86_64 ls /lib/modules/$(uname -r)
bls.conf config kernel modules.alias.bin modules.builtin.alias.bin modules.builtin.modinfo modules.dep.bin modules.order modules.symbols source vmlinuz build extra modules.alias modules.builtin modules.builtin.bin modules.dep modules.devname modules.softdep modules.symbols.bin System.map

ls /lib/modules/$(uname -r)/extra v4l2loopback

Error while running modprobe - modprobe: ERROR: could not insert 'v4l2loopback': Key was rejected by service

Error While Installation:

/usr/src/v4l2loopback-v0.12.7 /home/boffice/tmp/cam rm -f *~ rm -f Module.symvers Module.markers modules.order make -C /lib/modules/uname -r/build M=/usr/src/v4l2loopback-v0.12.7 clean make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64' make[1]: *** No rule to make target 'clean'. Stop. make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64' make: *** [Makefile:63: clean] Error 2 Building v4l2-loopback driver... make -C /lib/modules/uname -r`/build M=/usr/src/v4l2loopback-v0.12.7 modules
make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make[1]: *** No rule to make target 'modules'. Stop.
make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'```
make: *** [Makefile:43: v4l2loopback.ko] Error 2

When you see 
  *** No rule to make target 'clean'.  Stop. 
Probably kernel-headers and kernel do not have the same version… Install, reboot and try again!
otherwise you could try running 'dnf donwgrade gcc' https://ask.fedoraproject.org/t/fedora-34-beta-and-oot-kmod-nvidia-virtualbox-v4l2loopback-etc/12778

[info] Cert Password:
[info] 8c2c882e4c6e
make -C /lib/modules/uname -r/build M=/usr/src/v4l2loopback-v0.12.7 modules_install
make[1]: Entering directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make[1]: *** No rule to make target 'modules_install'. Stop.
make[1]: Leaving directory '/usr/src/kernels/5.17.12-1.surface.fc36.x86_64'
make: *** [Makefile:47: install] Error 2
v4l2loopback
[info] Now Manually singing
[warn] there might be no file to sign. Please check /lib/modules/5.17.12-1.surface.fc36.x86_64/extra/v4l2loopback
[info] Cert Password:
[info] 8c2c882e4c6e
./key.sh: line 74: /usr/src/kernels/5.17.12-1.surface.fc36.x86_64/scripts/sign-file: No such file or directory
./key.sh: line 75: /usr/src/kernels/5.17.12-1.surface.fc36.x86_64/scripts/sign-file: No such file or directory
[info] finished signing_ko
/home/boffice/tmp/cam
modprobe: ERROR: could not insert 'v4l2loopback': Key was rejected by service
filename: /lib/modules/5.17.12-1.surface.fc36.x86_64/extra/v4l2loopback/v4l2loopback.ko.xz
license: GPL
author: Vasily Levin, IOhannes m zmoelnig [email protected],Stefan Diewald,Anton Novikovet al.
description: V4L2 loopback video device
rhelversion: 9.99
depends: videodev
retpoline: Y
name: v4l2loopback
vermagic: 5.17.12-1.surface.fc36.x86_64 SMP preempt mod_unload
parm: debug:debugging level (higher values == more verbose) (int)
parm: max_buffers:how many buffers should be allocated (int)
parm: max_openers:how many users can open loopback device (int)
parm: devices:how many devices should be created (int)
parm: video_nr:video device numbers (-1=auto, 0=/dev/video0, etc.) (array of int)
parm: card_label:card labels for every device (array of charp)
parm: exclusive_caps:whether to announce OUTPUT/CAPTURE capabilities exclusively or not (array of bool)
parm: max_width:maximum frame width (int)
parm: max_height:maximum frame height (int)

I'm also using fedora 36 and surface kernel

It appears that your module is still not signed yet. also you don't have the sign-file script in your system.
./key.sh: line 74: /usr/src/kernels/5.17.12-1.surface.fc36.x86_64/scripts/sign-file: No such file or directory
Have you installed package kernel-surface-devel yet?

once you're installed try to manual sign the module with the step I provided above.
I had posted more details in this thread as well, look it up.

@2ndBillGates
Copy link

Also, if you want to install module to Surface Kernel. check this out
https://github.com/linux-surface/linux-surface/issues/803#issuecomment-1128410963

@2ndBillGates
Copy link

sorry for the broken link
Here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment