diff --git a/.gitignore b/.gitignore index 5ee34c8..cb5658d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ *.xz *.bz2 *.rpm +.claude/ +TODO.md +CLAUDE.local.md diff --git a/howdy-beta/99-howdy-video.rules b/howdy-beta/99-howdy-video.rules new file mode 100644 index 0000000..b62b33a --- /dev/null +++ b/howdy-beta/99-howdy-video.rules @@ -0,0 +1,5 @@ +# Howdy video device access rules +# Allow users in the video group to access video devices for face recognition + +# Grant video group read/write access to video devices +KERNEL=="video[0-9]*", GROUP="video", MODE="0660" diff --git a/howdy-beta/deps/python-dlib/python-dlib.spec b/howdy-beta/deps/python-dlib/python-dlib.spec new file mode 100644 index 0000000..5e095cb --- /dev/null +++ b/howdy-beta/deps/python-dlib/python-dlib.spec @@ -0,0 +1,208 @@ +%global forgeurl https://github.com/davisking/dlib + +# Compiling and running tests takes quite long and is resource intensive. +# Turn them off using `--without ctest`. +%bcond ctest 0 + +Name: dlib +Version: 20.0 +Release: %autorelease +Summary: A modern C++ toolkit containing machine learning algorithms +%forgemeta +License: BSL-1.0 +URL: http://dlib.net +Source: %forgesource +# Fix build issue with Python 3.14 +Patch: https://github.com/davisking/dlib/pull/3098.patch + +BuildRequires: boost-devel +BuildRequires: cmake +BuildRequires: cmake(pybind11) +BuildRequires: gcc-c++ +BuildRequires: gcc-gfortran +BuildRequires: pkgconfig(fftw3) +# BLAS and LAPACK support +# We need to depend on `flexiblas` rather than `cblas` and `lapack` +# https://docs.fedoraproject.org/en-US/packaging-guidelines/BLAS_LAPACK/ +BuildRequires: pkgconfig(flexiblas) +BuildRequires: pkgconfig(libavcodec) +BuildRequires: pkgconfig(libavdevice) +BuildRequires: pkgconfig(libavfilter) +BuildRequires: pkgconfig(libavformat) +BuildRequires: pkgconfig(libavutil) +BuildRequires: pkgconfig(libpng) +BuildRequires: pkgconfig(libjpeg) +BuildRequires: pkgconfig(libjxl) +BuildRequires: pkgconfig(libswresample) +BuildRequires: pkgconfig(libswscale) +BuildRequires: pkgconfig(libwebp) +BuildRequires: pkgconfig(python3) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(x11) +BuildRequires: python3dist(pytest) +BuildRequires: python3dist(more-itertools) +BuildRequires: time + +# Stop building for i686 +# https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval +# While fix_aarch64.patch (see above) also fixes the s390x build of tests, +# running those tests results in lots of failures and even coredumps. +ExcludeArch: %{ix86} s390x + +%description +Dlib is a general purpose cross-platform open source software library written +in the C++ programming language. Its design is heavily influenced by ideas from +design by contract and component-based software engineering. It contains +components for dealing with networking, threads, graphical user interfaces, +data structures, linear algebra, machine learning, image processing, data +mining, XML and text parsing, numerical optimization, Bayesian networks, and +numerous other tasks. + + +%package devel +Summary: Development files for dlib +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +Dlib is a general purpose cross-platform open source software library written +in the C++ programming language. This package contains development files for +the library. + + +%package -n python3-%{name} +Summary: Python 3 interface to %{name} + +%description -n python3-%{name} +Dlib is a general purpose cross-platform open source software library written +in the C++ programming language. This package contains Python 3 API for the +library. + + +%package doc +Summary: Documentation for dlib +License: CC0-1.0 AND CC-BY-SA-3.0 +Requires: %{name} = %{version}-%{release} +BuildArch: noarch + +%description doc +Dlib is a general purpose cross-platform open source software library written +in the C++ programming language. This package contains the library +documentation and examples. + + +%prep +%forgeautosetup -p1 + +find docs -type f -exec chmod 644 {} + +find examples -type f -exec chmod 644 {} + + +# Remove empty files +find docs/docs -size 0 -print -delete + +# Move license files out of examples +mv -v examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt . +mv -v examples/video_frames/license.txt video_frames_license.txt + +# unbundle pybind11, see https://bugzilla.redhat.com/2098694 +rm -r dlib/external/pybind11 +sed -i 's@add_subdirectory(../../dlib/external/pybind11 pybind11_build)@find_package(pybind11 CONFIG)@' tools/python/CMakeLists.txt + +# Do not treat warnings as errors when compiling tests +sed -r -i 's/[[:space:]]+-Werror//' dlib/test/CMakeLists.txt + + +%generate_buildrequires +%pyproject_buildrequires + + +%build +# dlib requires `libjxl_cms` provided by libjxl >= 0.10` currently only +# available in rawhide (F41) +%cmake \ + -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \ + -DDLIB_USE_CUDA:BOOL=OFF \ +%if 0%{?fedora} >= 41 + -DDLIB_JXL_SUPPORT:BOOL=ON +%else + -DDLIB_JXL_SUPPORT:BOOL=OFF +%endif +%cmake_build + +%if %{with ctest} +# Use `-O` instead of `-O2`. Reduces max memory for single thread from +# 17GB to 12GB. It also reduces time to build. +# Also reduce debuginfo using `-g1` instead of `-g` (aka `-g2`). +# Memory consumption drops further to ~6GiB and build speeds up again. +CXXFLAGS="${CXXFLAGS/-O2/-O}" +CXXFLAGS="${CXXFLAGS/-g /-g1 }" + +# Unit tests +# +# On small builders (~15GiB) the build fails running out of memory. +# With a few tweaks memory consumption peaks at just over 6GiB. +# Constrain the build to 7GiB per core. +# +# RHEL doesn't support `%%constrain_build` nor `%%{limit_build ...}`. + +MAX_CPUS="$(($(cat /proc/meminfo | grep MemTotal | awk '{print $2}') / $((7168 * 1024))))" +%global _smp_mflags "-j${MAX_CPUS}" + +pushd dlib/test +%cmake \ + -DDLIB_USE_CUDA:BOOL=OFF \ +%if 0%{?fedora} >= 41 + -DDLIB_JXL_SUPPORT:BOOL=ON +%else + -DDLIB_JXL_SUPPORT:BOOL=OFF +%endif +%cmake_build +popd +%endif + +%pyproject_wheel + + +%install +%cmake_install + +%pyproject_install +%pyproject_save_files %{?fedora:-l} %{name} + +find %{buildroot} -name '.*' -exec rm -rf {} + + + +%check +%if %{with ctest} +pushd dlib/test/redhat-linux-build +# tests can be disabled using `--no_${TEST}` with --runall or +# enabled `--${TEST}` without it. `-h` shows all tests. +# test_ffmpeg fails +./dtest --runall --no_test_ffmpeg +popd +%endif +%pytest -v + + +%files +%license LICENSE.txt +%{_libdir}/libdlib.so.20* + +%files devel +%{_libdir}/libdlib.so +%{_includedir}/dlib/ +%{_libdir}/cmake/dlib/ +%{_libdir}/pkgconfig/*.pc + +%files -n python3-%{name} -f %{pyproject_files} +%{python3_sitearch}/_%{name}_pybind11%{python3_ext_suffix} +%doc README.md + +%files doc +%doc docs/docs/ +%doc examples +%license LICENSE_FOR_EXAMPLE_PROGRAMS.txt +%license video_frames_license.txt + + +%changelog +%autochangelog diff --git a/howdy-beta/howdy-authselect/90-howdy-authselect.preset b/howdy-beta/howdy-authselect/90-howdy-authselect.preset new file mode 100644 index 0000000..21e7804 --- /dev/null +++ b/howdy-beta/howdy-authselect/90-howdy-authselect.preset @@ -0,0 +1,2 @@ +# Enable howdy PAM patching service to watch for authselect changes +enable howdy-authselect.path diff --git a/howdy-beta/howdy-authselect/README.md b/howdy-beta/howdy-authselect/README.md new file mode 100644 index 0000000..1b2c3ea --- /dev/null +++ b/howdy-beta/howdy-authselect/README.md @@ -0,0 +1,69 @@ +# howdy-authselect + +> **Warning**: This is a gruesome AI-dreamed hack. + +## The Problem + +Fedora's `authselect` manages PAM configuration through profiles. These profiles are "all or nothing" - you cannot extend an existing profile with additional features without copying and maintaining the entire profile. + +The upstream profiles (sssd, local, etc.) include features like `with-fingerprint` for fprintd, but there's no `with-howdy` option. Adding one would require: + +1. Copying the entire profile (system-auth, password-auth, fingerprint-auth, smartcard-auth, postlogin, nsswitch.conf, dconf-db, dconf-locks, README, REQUIREMENTS) +2. Adding our single line for pam_howdy.so +3. Maintaining this copy forever as upstream authselect evolves + +This is unsustainable for a single PAM module addition. + +## The Hack + +Instead of maintaining full profile copies, this package: + +1. Lets authselect manage PAM configuration normally +2. Patches in `pam_howdy.so` after the fact +3. Uses a systemd path unit to re-apply the patch whenever authselect regenerates the config + +This is ugly but pragmatic. We inject one line: + +``` +auth sufficient pam_howdy.so +``` + +## Usage + +```bash +# Enable howdy in PAM (run once after installing howdy) +sudo howdy-authselect enable + +# Enable automatic re-patching after authselect changes +sudo systemctl enable --now howdy-authselect.path + +# Check status +howdy-authselect status + +# Disable if needed +sudo howdy-authselect disable +``` + +## Why Not Upstream? + +The proper fix would be for authselect to support `with-howdy` natively, similar to `with-fingerprint`. This would require: + +1. Acceptance of howdy as a supported authentication method in Fedora +2. Patches to the authselect package itself +3. Coordination with the authselect maintainers + +Until then, we hack. + +## Immutable Distros (Silverblue/Kinoite/Bazzite) + +This hack should work on immutable Fedora variants because: + +- `/etc/authselect/` is part of the writable `/etc` overlay +- The systemd path unit watches files in `/etc`, which is persistent +- `rpm-ostree install howdy howdy-authselect` layers both packages + +After layering and rebooting: +```bash +sudo howdy-authselect enable +sudo systemctl enable --now howdy-authselect.path +``` diff --git a/howdy-beta/howdy-authselect/howdy-authselect b/howdy-beta/howdy-authselect/howdy-authselect new file mode 100644 index 0000000..6151e78 --- /dev/null +++ b/howdy-beta/howdy-authselect/howdy-authselect @@ -0,0 +1,195 @@ +#!/bin/bash +# howdy-authselect - Enable/disable howdy face authentication in PAM +# +# WARNING: This is a gruesome AI-dreamed hack. +# +# Fedora's authselect has an "all or nothing" profile problem - you cannot +# extend profiles, only replace them entirely. Rather than maintaining full +# copies of upstream profiles just to add one PAM module, this script patches +# pam_howdy.so into the existing authselect-managed configuration. +# +# It can be run manually or triggered automatically via systemd path unit. + +set -euo pipefail + +# Both files need patching: system-auth (sudo, etc) and password-auth (GDM, login) +AUTH_FILES=( + "/etc/authselect/system-auth" + "/etc/authselect/password-auth" +) +PAM_HOWDY="/usr/lib64/security/pam_howdy.so" +HOWDY_LINE="auth sufficient pam_howdy.so" +# Insert after this pattern (pam_faillock preauth line or early auth line) +INSERT_AFTER="pam_faillock.so preauth" + +usage() { + cat <&2 + exit 1 + fi +} + +check_pam_module() { + if [[ ! -f "$PAM_HOWDY" ]]; then + echo "Error: pam_howdy.so not found at $PAM_HOWDY" >&2 + echo "Please install the howdy package first." >&2 + exit 1 + fi +} + +check_authselect() { + for auth_file in "${AUTH_FILES[@]}"; do + if [[ ! -f "$auth_file" ]]; then + echo "Error: $auth_file not found" >&2 + echo "authselect does not appear to be managing PAM configuration." >&2 + exit 1 + fi + done +} + +is_howdy_enabled_in_file() { + local file="$1" + grep -q "pam_howdy.so" "$file" 2>/dev/null +} + +is_howdy_enabled() { + # Check if enabled in all files + for auth_file in "${AUTH_FILES[@]}"; do + if ! is_howdy_enabled_in_file "$auth_file"; then + return 1 + fi + done + return 0 +} + +enable_file() { + local auth_file="$1" + + if is_howdy_enabled_in_file "$auth_file"; then + echo "howdy already enabled in $(basename "$auth_file")" + return 0 + fi + + # Create backup + cp "$auth_file" "${auth_file}.bak" + + # Insert howdy line after pam_faillock preauth (or after pam_faildelay if no faillock) + if grep -q "$INSERT_AFTER" "$auth_file"; then + sed -i "/$INSERT_AFTER/a\\$HOWDY_LINE" "$auth_file" + else + # Fallback: insert after pam_faildelay + sed -i "/pam_faildelay.so/a\\$HOWDY_LINE" "$auth_file" + fi + + if is_howdy_enabled_in_file "$auth_file"; then + echo "howdy enabled in $(basename "$auth_file")" + else + echo "Error: Failed to enable howdy in $auth_file" >&2 + mv "${auth_file}.bak" "$auth_file" + return 1 + fi +} + +disable_file() { + local auth_file="$1" + + if ! is_howdy_enabled_in_file "$auth_file"; then + echo "howdy not enabled in $(basename "$auth_file")" + return 0 + fi + + # Create backup + cp "$auth_file" "${auth_file}.bak" + + # Remove howdy line + sed -i '/pam_howdy.so/d' "$auth_file" + + if ! is_howdy_enabled_in_file "$auth_file"; then + echo "howdy disabled in $(basename "$auth_file")" + else + echo "Error: Failed to disable howdy in $auth_file" >&2 + mv "${auth_file}.bak" "$auth_file" + return 1 + fi +} + +enable_howdy() { + check_root + check_pam_module + check_authselect + + local failed=0 + for auth_file in "${AUTH_FILES[@]}"; do + enable_file "$auth_file" || failed=1 + done + + if [[ $failed -eq 0 ]]; then + echo "howdy enabled successfully in PAM configuration" + else + echo "Error: Failed to enable howdy in some files" >&2 + exit 1 + fi +} + +disable_howdy() { + check_root + check_authselect + + local failed=0 + for auth_file in "${AUTH_FILES[@]}"; do + disable_file "$auth_file" || failed=1 + done + + if [[ $failed -eq 0 ]]; then + echo "howdy disabled successfully in PAM configuration" + else + echo "Error: Failed to disable howdy in some files" >&2 + exit 1 + fi +} + +show_status() { + check_authselect + + for auth_file in "${AUTH_FILES[@]}"; do + if is_howdy_enabled_in_file "$auth_file"; then + echo "$(basename "$auth_file"): ENABLED" + else + echo "$(basename "$auth_file"): DISABLED" + fi + done +} + +case "${1:-}" in + enable) + enable_howdy + ;; + disable) + disable_howdy + ;; + status) + show_status + ;; + -h|--help|help) + usage + ;; + *) + usage + exit 1 + ;; +esac diff --git a/howdy-beta/howdy-authselect/howdy-authselect.path b/howdy-beta/howdy-authselect/howdy-authselect.path new file mode 100644 index 0000000..dcd7a8e --- /dev/null +++ b/howdy-beta/howdy-authselect/howdy-authselect.path @@ -0,0 +1,10 @@ +[Unit] +Description=Watch for authselect configuration changes +Documentation=man:howdy(1) + +[Path] +PathChanged=/etc/authselect/system-auth +PathChanged=/etc/authselect/password-auth + +[Install] +WantedBy=multi-user.target diff --git a/howdy-beta/howdy-authselect/howdy-authselect.service b/howdy-beta/howdy-authselect/howdy-authselect.service new file mode 100644 index 0000000..432b688 --- /dev/null +++ b/howdy-beta/howdy-authselect/howdy-authselect.service @@ -0,0 +1,10 @@ +[Unit] +Description=Re-enable howdy in PAM after authselect changes (gruesome hack) +Documentation=man:howdy(1) +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/howdy-authselect enable +# Small delay to ensure authselect has finished writing +ExecStartPre=/bin/sleep 1 diff --git a/howdy-beta/howdy-authselect/howdy-authselect.spec b/howdy-beta/howdy-authselect/howdy-authselect.spec new file mode 100644 index 0000000..19b929d --- /dev/null +++ b/howdy-beta/howdy-authselect/howdy-authselect.spec @@ -0,0 +1,80 @@ +Name: howdy-authselect +Version: 1.0.0 +Release: 2%{?dist} +Summary: Enable howdy face authentication in authselect-managed PAM + +License: MIT +URL: https://github.com/boltgolt/howdy + +Source0: howdy-authselect +Source1: howdy-authselect.service +Source2: howdy-authselect.path +Source3: 90-howdy-authselect.preset +Source4: README.md + +BuildArch: noarch + +BuildRequires: systemd-rpm-macros + +Requires: howdy +Requires: authselect +Requires: systemd + +%{?systemd_requires} + +%description +A gruesome hack to work around authselect's "all or nothing" profile problem. + +Fedora's authselect does not support extending profiles - you must copy and +maintain entire profiles to add a single PAM module. This package instead +patches pam_howdy.so into the existing authselect-managed configuration and +uses a systemd path unit to re-apply the patch when authselect regenerates +the PAM config. + +%prep +# Nothing to prep - sources are scripts + +%build +# Nothing to build + +%install +install -Dm 0755 %{SOURCE0} %{buildroot}%{_bindir}/howdy-authselect +install -Dm 0644 %{SOURCE1} %{buildroot}%{_unitdir}/howdy-authselect.service +install -Dm 0644 %{SOURCE2} %{buildroot}%{_unitdir}/howdy-authselect.path +install -Dm 0644 %{SOURCE3} %{buildroot}%{_prefix}/lib/systemd/system-preset/90-howdy-authselect.preset +install -Dm 0644 %{SOURCE4} %{buildroot}%{_docdir}/%{name}/README.md + +%post +%systemd_post howdy-authselect.path howdy-authselect.service +# On fresh install, enable the path unit and patch PAM +if [ $1 -eq 1 ]; then + systemctl preset howdy-authselect.path >/dev/null 2>&1 || : + systemctl start howdy-authselect.path >/dev/null 2>&1 || : + %{_bindir}/howdy-authselect enable >/dev/null 2>&1 || : +fi + +%preun +%systemd_preun howdy-authselect.path howdy-authselect.service +# On uninstall, remove howdy from PAM +if [ $1 -eq 0 ]; then + %{_bindir}/howdy-authselect disable >/dev/null 2>&1 || : +fi + +%postun +%systemd_postun_with_restart howdy-authselect.path howdy-authselect.service + +%files +%{_bindir}/howdy-authselect +%{_unitdir}/howdy-authselect.service +%{_unitdir}/howdy-authselect.path +%{_prefix}/lib/systemd/system-preset/90-howdy-authselect.preset +%{_docdir}/%{name}/README.md + +%changelog +* Sat Dec 06 2025 Ronny Pfannschmidt - 1.0.0-2 +- Add systemd preset file to auto-enable the path unit on install +- Run howdy-authselect enable during post-install to patch PAM immediately +- Run howdy-authselect disable during pre-uninstall to clean up PAM + +* Sat Dec 06 2025 Ronny Pfannschmidt - 1.0.0-1 +- Initial package diff --git a/howdy-beta/howdy.spec b/howdy-beta/howdy.spec index 03fbd40..5b599de 100644 --- a/howdy-beta/howdy.spec +++ b/howdy-beta/howdy.spec @@ -5,7 +5,7 @@ Name: howdy Version: 3.0.0 -Release: 7%{?dist} +Release: 9%{?dist} Summary: Windows Helloâ„¢ style authentication for Linux # The entire source code is GPL-3.0-or-later except: @@ -15,6 +15,8 @@ URL: %{forgeurl} Source0: %{forgesource} Source1: howdy_profile.sh Source2: howdy_profile.csh +Source3: howdy.te +Source4: 99-howdy-video.rules Source10: https://github.com/davisking/dlib-models/raw/master/dlib_face_recognition_resnet_model_v1.dat.bz2 Source11: https://github.com/davisking/dlib-models/raw/master/mmod_human_face_detector.dat.bz2 Source12: https://github.com/davisking/dlib-models/raw/master/shape_predictor_5_face_landmarks.dat.bz2 @@ -25,10 +27,13 @@ BuildRequires: gcc-c++ BuildRequires: meson BuildRequires: bzip2 BuildRequires: python3-devel +BuildRequires: selinux-policy +BuildRequires: policycoreutils-devel BuildRequires: pkgconfig(INIReader) BuildRequires: pkgconfig(libevdev) BuildRequires: pkgconfig(pam) +BuildRequires: systemd-rpm-macros Requires: hicolor-icon-theme Requires: python3dist(dlib) @@ -78,6 +83,11 @@ chmod 0755 howdy/src/compare.py # Disable downloading dlib-data files sed -i "/install_data('dlib-data\/install.sh',.*/d" howdy/src/meson.build +# Compile SELinux policy module +cp %{S:3} howdy.te +checkmodule -M -m -o howdy.mod howdy.te +semodule_package -o howdy.pp -m howdy.mod + %build %meson \ -Ddlib_data_dir=%{_datadir}/%{name}/dlib-data/ \ @@ -108,6 +118,42 @@ mkdir -p %{buildroot}%{_sysconfdir}/%{name}/models/ # install dlib-data files install -Dm 0644 howdy/src/dlib-data/*.dat -t %{buildroot}%{_datadir}/%{name}/dlib-data/ +# install the SELinux policy +install -Dm 0644 howdy.pp %{buildroot}%{_datadir}/selinux/targeted/howdy.pp + +# install udev rules for video device access +install -Dm 0644 %{S:4} %{buildroot}%{_udevrulesdir}/99-howdy-video.rules + +%post +# Install SELinux module +if command -v sestatus >/dev/null 2>&1 && sestatus | grep -q 'SELinux status:.*enabled'; then + # Check if the SELinux module is already installed + if ! semodule -l | grep -q howdy; then + # Load the SELinux policy module if it's not already loaded + semodule -i %{_datadir}/selinux/targeted/howdy.pp + fi +fi + +# Add gdm user to video group for GDM login face recognition +if getent passwd gdm >/dev/null 2>&1; then + if ! id -nG gdm 2>/dev/null | grep -qw video; then + usermod -aG video gdm 2>/dev/null || : + fi +fi + +# Reload udev rules +udevadm control --reload-rules 2>/dev/null || : +udevadm trigger --subsystem-match=video4linux 2>/dev/null || : + +%postun +# Uninstall SELinux module +if command -v sestatus >/dev/null 2>&1 && sestatus | grep -q 'SELinux status:.*enabled'; then + # Check if the howdy module is installed + if semodule -l | grep -q howdy; then + # Remove the howdy SELinux policy module + semodule -r howdy + fi +fi %files %license LICENSE @@ -125,6 +171,8 @@ install -Dm 0644 howdy/src/dlib-data/*.dat -t %{buildroot}%{_datadir}/%{name}/dl %dir %{_sysconfdir}/%{name}/models/ %config(noreplace) %{_sysconfdir}/%{name}/config.ini %config(noreplace) %{_sysconfdir}/profile.d/%{name}.* +%{_datadir}/selinux/*/howdy.pp +%{_udevrulesdir}/99-howdy-video.rules %files gtk %{_bindir}/%{name}-gtk @@ -138,6 +186,11 @@ install -Dm 0644 howdy/src/dlib-data/*.dat -t %{buildroot}%{_datadir}/%{name}/dl %{_datadir}/%{name}/dlib-data/*.dat %changelog +* Sat Dec 06 2025 Ronny Pfannschmidt - 3.0.0-8 +- Add SELinux policy for video device access +- Add udev rules for video device permissions +- Add gdm user to video group for GDM login support + * Sun Jul 20 2025 Arthur Bols - 3.0.0-7 - Remove dependency on ffmpeg-python diff --git a/howdy-beta/howdy.te b/howdy-beta/howdy.te new file mode 100644 index 0000000..848d6b6 --- /dev/null +++ b/howdy-beta/howdy.te @@ -0,0 +1,10 @@ +module howdy 1.0; + +require { + type xdm_t; + type v4l_device_t; + class chr_file map; +} + +#============= xdm_t ============== +allow xdm_t v4l_device_t:chr_file map;