Skip to content

udevCheckHook: init#407629

Merged
r-vdp merged 1 commit intoNixOS:masterfrom
LordGrimmauld:udev-check-hook
May 20, 2025
Merged

udevCheckHook: init#407629
r-vdp merged 1 commit intoNixOS:masterfrom
LordGrimmauld:udev-check-hook

Conversation

@LordGrimmauld
Copy link
Contributor

@LordGrimmauld LordGrimmauld commented May 16, 2025

Usage:

nativeBuildInputs = [
  udevCheckHook
];

doInstallCheck = true;

This hook executes udevadm verify --resolve-names=never --no-style on all outputs that have /etc/udev/rules.d.
This us a logical part of #404323 to check packages that supply udev rules.

Note this hook introduces a dependency on systemdMinimal, meaning this can't check systemdMinimal or its dependencies.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@LordGrimmauld LordGrimmauld requested review from jtojnar and r-vdp May 16, 2025 13:43
@LordGrimmauld
Copy link
Contributor Author

cc @yshui, can't review-request you as you are not on the maintainers list.

@LordGrimmauld
Copy link
Contributor Author

Adding this hook to brscan5 does fail loud and clear:

Running phase: installCheckPhase
@nix {"action":"setPhase","phase":"installCheckPhase"}
Executing udevCheckPhase
Configuration file /nix/store/6bh2vb0j6apxnvw07xxxsbxwnx3g246a-brscan5-1.3.1-0/etc/udev/rules.d/49-brother-mfp-brscan5-1.0.2-2.rules is marked executable. Please remove executable permission bits. Proceeding anyway.
/nix/store/6bh2vb0j6apxnvw07xxxsbxwnx3g246a-brscan5-1.3.1-0/etc/udev/rules.d/49-brother-mfp-brscan5-1.0.2-2.rules:17 Invalid key 'SYSFS'.
/nix/store/6bh2vb0j6apxnvw07xxxsbxwnx3g246a-brscan5-1.3.1-0/etc/udev/rules.d/49-brother-mfp-brscan5-1.0.2-2.rules: udev rules check failed.

1 udev rules files have been checked.
  Success: 0
  Fail:    1

@github-actions github-actions bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels May 16, 2025
@r-vdp
Copy link
Contributor

r-vdp commented May 16, 2025

I like the idea, but it would be great if we could somehow include this by default. The issue probably being that we can only include this for packages that aren't in the dependency closure of systemdMinimal. I don't know if there is any way to do that (how do we deal with other hooks that are enabled by default? They will at least depend on some things like bash, coreutils, etc).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! But for nix, both is actually valid:

description = ''
List of packages containing {command}`udev` rules.
All files found in
{file}`«pkg»/etc/udev/rules.d` and
{file}`«pkg»/lib/udev/rules.d`
will be included.
'';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we could maybe even simplify this:

apply = map lib.getBin;

Seems like udev outputs are only in the $bin output, tho i have to figure out how to get only the bin output.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use indirect variable access: ${!outputBin}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. Should be good now!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though unless this is ensured on package basis (e.g. in

), you probably still want to check all outputs.

For example, if the package has out and lib outputs, and the project uses libdir variable to install the files, they will end up in lib output while outputBin will point to out.

Though such packages need to be passed to services.udev.packages with explicit output for lib.getOutput "bin" to find them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grepping, I see at least one package that has the files in non-bin output:

configureFlags = [ "--with-udev=${placeholder "out"}/lib/udev" ];

services.udev.packages = [ pkgs.libmtp.out ];

Copy link
Member

@jtojnar jtojnar May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I am not even sure why the module is looking to bin output in the first place. I would expect it in out output if:

If package has daemon and bindir programs in separate outputs, they should be in out and bin respectively, and in that case I would expect the udev files in out output.

Edit: Looks like it has been discussed on the commit that introduced the getBin cd5dd9f and a PR was opened but it fizzled out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright, i'll restore the for loop for all outputs!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and the module might need a fix later, i too was surprised it looks in $bin first)

@LordGrimmauld
Copy link
Contributor Author

it would be great if we could somehow include this by default.

I'd agree, but i honestly have no idea how to make that happen either. The doc on check hooks is kinda lacking.
That said: I am not 100% certain that'd be a good idea. Adding a hook to everything is basically a world rebuild (=couldn't happen in a PR to master), the fallout would be hard to locate, and literally every package (with or without udev rules) would go through the hook code path checking for udev outputs.

@r-vdp
Copy link
Contributor

r-vdp commented May 16, 2025

Yeah. But these hooks are also really not very discoverable, so I doubt that many packages will use this. We can of course add it incrementally to packages that caused nixos builds to fail, to avoid regressions, that's very valuable already (but still needs a way to point people to this option).

@LordGrimmauld
Copy link
Contributor Author

Yeah. But these hooks are also really not very discoverable

How about a follow-up treewide that adds the hook to all packages with udev output? nix-locate can trivially find all packages with udev output.

@LordGrimmauld LordGrimmauld force-pushed the udev-check-hook branch 2 times, most recently from 8964a2d to 267649e Compare May 16, 2025 14:12
Copy link
Contributor

@drupol drupol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the shellcheck output:

❯ shellcheck pkgs/by-name/ud/udevCheckHook/hook.sh

In pkgs/by-name/ud/udevCheckHook/hook.sh line 1:
udevCheckHook() {
^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.


In pkgs/by-name/ud/udevCheckHook/hook.sh line 9:
        if [ -d "${!outputBin}/$path/udev/rules.d" ]; then
                 ^-----------^ SC2154 (warning): outputBin is referenced but not assigned.

For more information:
  https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y...
  https://www.shellcheck.net/wiki/SC2154 -- outputBin is referenced but not a...

Perhaps we could ignore1 those two issues with a comment?

Footnotes

  1. https://github.com/koalaman/shellcheck/wiki/Ignore

Usage:
```nix
nativeBuildInputs = [
  udevCheckHook
];
doInstallCheck = true;
```

This hook executes `udevadm verify --resolve-names=never --no-style`
on all outputs that have `/etc/udev/rules.d`.
This us a logical part of NixOS#404323 to check packages that supply udev rules.

Note this hook introduces a dependency on `systemdMinimal`,
meaning this can't check systemdMinimal or its dependencies.
@r-vdp
Copy link
Contributor

r-vdp commented May 16, 2025

Yeah. But these hooks are also really not very discoverable

How about a follow-up treewide that adds the hook to all packages with udev output? nix-locate can trivially find all packages with udev output.

Yeah we could do a one-off effort like that, but that won't ensure that future packages will have the hook added. But ok, perfect is the enemy of good, these are not arguments against this PR, just reflections triggered by it.

@yshui
Copy link
Contributor

yshui commented May 18, 2025

thank you for working on this! ❤️

Yeah we could do a one-off effort like that, but that won't ensure that future packages will have the hook added.

would it be possible to make it a CI check? i.e. if derivation outputs contain udev rules, check if the check hook is in build inputs?

@LordGrimmauld
Copy link
Contributor Author

would it be possible to make it a CI check? i.e. if derivation outputs contain udev rules, check if the check hook is in build inputs?

not really i think.

@LordGrimmauld
Copy link
Contributor Author

What is missing here to get this moved forward / merged?

@LordGrimmauld
Copy link
Contributor Author

LordGrimmauld commented May 20, 2025

As to packages requiring the hook:

nix-locate -t d --at-root -w --minimal -r '/(etc|lib)/udev/rules.d'

The following packages would be affected:

zsa-udev-rules.out					linuxKernel.packages.linux_libre.openrazer.out		indi-3rdparty.indi-orion-ssg3.out
(zsnes.out)						linuxKernel.packages.linux_6_1.openrazer.out		indilib.out
zfs.out							linuxKernel.packages.linux_xanmod.openrazer.out		indi-full.out
zfs_2_2.out						linuxKernel.packages.linux_ham.openrazer.out		indi-3rdparty.indi-webcam.out
yubikey-personalization.out				linuxKernel.packages.linux_zen.openrazer.out		indi-3rdparty.indi-weewx-json.out
xpra.out						linuxKernel.packages.linux_xanmod_stable.openrazer.out	infnoise.out
xr-hardware.out						openocd-rp2040.out					inkscape-extensions.silhouette.out
xfel.out						linuxKernel.packages.linux_6_14.openrazer.out		imsprog.out
xe-guest-utilities.out					linuxKernel.packages.linux_lqx.openrazer.out		indi-3rdparty.indi-gpsd.out
xf86_input_wacom.out					openocd.out						(indi-3rdparty.indi-fli.out)
xorg.xf86inputvmmouse.out				linuxKernel.packages.linux_6_6.openrazer.out		(indi-3rdparty.indi-apogee.out)
wooting-udev-rules.out					linuxKernel.packages.linux_5_10_hardened.openrazer.out	incus-lts.agent_loader
(wine.out)						linuxKernel.packages.linux_6_13_hardened.openrazer.out	incus.agent_loader
wch-isp.out						openobex.out						indi-3rdparty.indi-armadillo-platypus.out
waagent.out						linuxKernel.packages.linux_5_15.openrazer.out		indi-3rdparty.indi-aagcloudwatcher-ng.out
vial.out						linuxKernel.packages.linux_6_1_hardened.openrazer.out	indi-3rdparty.indi-gpio.out
via.out							linuxKernel.packages.linux_5_15_hardened.openrazer.out	indi-3rdparty.indi-aok.out
uvcdynctrl.out						linuxKernel.packages.linux_6_6_hardened.openrazer.out	indi-3rdparty.indi-avalonud.out
v4l-utils.out						openhantek6022.out					indi-3rdparty.indi-avalon.out
upower.out						opencbm.out						indi-3rdparty.indi-dsi.out
usb-modeswitch-data.out					openambit.out						indi-3rdparty.indi-astarbox.out
usb-blaster-udev-rules.out				openiscsi.out						indi-3rdparty.indi-celestronaux.out
usbmuxd2.out						open-vm-tools.out					indi-3rdparty.indi-bresserexos2.out
usbrelayd.out						open-vm-tools-headless.out				indi-3rdparty.indi-apogee.out
usbkvm.out						(ocf-resource-agents.out)				indi-3rdparty.indi-ffmv.out
usbmuxd.out						linuxKernel.packages.linux_6_12.nxp-pn5xx.out		indi-3rdparty.indi-duino.out
usbsdmux.out						linuxKernel.packages.linux_5_15.nxp-pn5xx.out		indi-3rdparty.indi-fishcamp.out
uuu.out							linuxKernel.packages.linux_xanmod_stable.nxp-pn5xx.out	indi-3rdparty.indi-gphoto.out
ubertooth.out						linuxKernel.packages.linux_xanmod.nxp-pn5xx.out		indi-3rdparty.indi-eqmod.out
udisks.out						linuxKernel.packages.linux_hardened.nxp-pn5xx.out	indi-3rdparty.indi-gige.out
uhd.out							linuxKernel.packages.linux_6_13.nxp-pn5xx.out		indi-3rdparty.indi-fli.out
tsduck.out						linuxKernel.packages.linux_libre.nxp-pn5xx.out		indi-3rdparty.indi-beefocus.out
trezor-udev-rules.out					linuxKernel.packages.linux_6_1.nxp-pn5xx.out		(indi-3rdparty.indi-fishcamp.out)
tiscamera.out						linuxKernel.packages.linux_6_1_hardened.nxp-pn5xx.out	utsushi.out
tlp.out							linuxKernel.packages.linux_5_4.nxp-pn5xx.out		iio-sensor-proxy.out
torzu.out						linuxKernel.packages.linux_zen.nxp-pn5xx.out		huion-switcher.out
thunderbolt.out						linuxKernel.packages.linux_6_14.nxp-pn5xx.out		hplip.out
tiny-dfr.out						linuxKernel.packages.linux_5_15_hardened.nxp-pn5xx.out	headsetcontrol.out
systemd.out						linuxKernel.packages.linux_lqx.nxp-pn5xx.out		heimdall.out
systemdMinimal.out					linuxKernel.packages.linux_5_10_hardened.nxp-pn5xx.out	heimdall-gui.out
system-config-printer.out				linuxKernel.packages.linux_ham.nxp-pn5xx.out		hdapsd.out
systemdUkify.out					linuxKernel.packages.linux_6_13_hardened.nxp-pn5xx.out	(heroic.out)
suyu.out						linuxKernel.packages.linux_6_6_hardened.nxp-pn5xx.out	handheld-daemon.out
swayosd.out						nxpmicro-mfgtools.out					hackrf.out
supergfxctl.out						numworks-udev-rules.out					gummy.out
super-slicer-beta.out					nut.out							gradm.out
super-slicer.out					nvme-cli.out						gpsd.out
sunshine.out						linuxKernel.packages.linux_6_6.nxp-pn5xx.out		google-guest-configs.out
steam-devices-udev-rules.out				ns-usbloader.out					google-compute-engine.out
stlink-gui.out						nitrokey-udev-rules.out					goxlr-utility.out
stlink.out						nfs-utils.out						gobi_loader.out
streamcontroller.out					networkmanager.out					gnome-settings-daemon46.out
streamdeck-ui.out					mutter46.out						gnome-settings-daemon.out
stratisd.out						mutter.out						gmobile.out
stratisd.initrd						multipath-tools.out					glasgow.out
(steam-fhsenv-without-steam.out)			mouse-actions-gui.out					gfs2-utils.out
(steam-run-free.out)					mouse-actions.out					gdm.out
speakersafetyd.out					mouse_m908.out						g810-led.out
sparrow-unwrapped.out					moolticute.udev						game-devices-udev-rules.out
solo2-cli.out						modemmanager.out					fuse3.udev
solaar.out						(mkosi.out)						foo2zjs.out
solaar.udev						minipro.out						footswitch.out
(sparrow.out)						meletrix-udev-rules.out					flashprog.out
soapysdr-with-plugins.out				media-player-info.out					flashrom.out
python312Packages.soapysdr-with-plugins.out		mdevctl.out						feedbackd.out
python313Packages.soapysdr-with-plugins.out		mdadm.out						ffado-mixer.out
snagboot.out						mate.mate-settings-daemon.out				ffado.out
sc-controller.out					m33-linux.out						eudev.out
sane-backends.out					luminance.out						epsonscan2.out
rust-streamdeck.out					lvm2_vdo.out						em100.out
rwedid.out						lvm2_dmeventd.out					elogind.out
rtl_fm_streamer.out					lvm2.out						eg25-manager.out
rtl-sdr.out						(lutris-free.out)					edgetx.out
rtl-sdr-librtlsdr.out					ltunify.out						ecpdap.out
rtl-sdr-osmocom.out					lm4flash.out						easypdkprog.out
rpcs3.out						linuxConsoleTools.out					drbd.out
roccat-tools.out					liquidctl.out						dsview.out
rkdeveloptool-pine64.out				linux-gpib.out						dolphin-emu.out
rfkill_udev.out						limesuiteWithGui.out					dolphin-emu-primehack.out
rdma-core.out						limesuite.out						dmrconfig.out
quark-goldleaf.out					light.out						direwolf.out
qmk-udev-rules.out					libwebcam.out						digitalbitbox.out
qlcplus.out						libwacom-surface.out					dediprog-sf100.out
qFlipper.out						libwacom.out						deepin.dde-daemon.out
qdmr.out						libsigrok.out						ddcutil.out
python313Packages.seabreeze.out				libticables2.out					(dduper.out)
python313Packages.sigrok.out				libuldaq.out						dataexplorer.out
python313Packages.py3buddy.out				libpsm2.out						cutecapture.out
python313Packages.openant.out				libinput.out						(cura-appimage.out)
python313Packages.liquidctl.out				libirecovery.out					cpu-energy-meter.out
python313Packages.google-compute-engine.out		libjaylink.out						colord.out
python313Packages.busylight-for-humans.out		libmtp.out						comedilib.out
python312Packages.sigrok.out				libnitrokey.out						cm-rgb.out
python312Packages.seabreeze.out				libfprint.out						ckb-next.out
python312Packages.rfcat.out				libfprint-tod.out					chrysalis.out
rivalcfg.out						libftdi1.out						ccid.out
python312Packages.py3buddy.out				libfido2.out						cc-tool.out
persistent-evdev.out					libgphoto2.out						casync.out
python312Packages.openant.out				libgpod.out						btrfs-progs.out
python312Packages.busylight-for-humans.out		libiio.out						brillo.out
boxflat.out						python313Packages.libiio.out				brltty.out
pulseaudioFull.out					libedgetpu.out						brightnessctl.out
pulseaudio.out						libbladeRF.out						bolt.out
proxmark3.out						ledger-udev-rules.out					(bottles.out)
prusa-slicer.out					k40-whisperer.out					bmputil.out
projecteur.out						joycond.out						bluez.out
polar.out						ipp-usb.out						bluez-experimental.out
platformio-core.udev					iptsd.out						libsForQt5.bluez-qt.bin
libsForQt5.plasma-remotecontrollers.out			ipad_charge.out						bitbox.out
pipewire.out						input-remapper.out					bitbox-bridge.out
picotool.out						inputmodule-control.out					bcache-tools.out
picoprobe-udev-rules.out				indi-3rdparty.indi-sx.out				bazecor.out
phodav.out						indi-3rdparty.indi-talon6.out				bcachefs-tools.out
pcmciaUtils.out						indi-3rdparty.indi-nexdome.out				autorandr.out
oversteer.out						indi-3rdparty.indi-mgen.out				asusctl.out
orbuculum.out						indi-3rdparty.indi-nut.out				asdbctl.out
openterface-qt.out					indi-3rdparty.indi-maxdomeii.out			(artisan.out)
opentabletdriver.out					indi-3rdparty.indi-gpsnmea.out				argyllcms.out
opentx.out						indi-3rdparty.indi-shelyak.out				apio-udev-rules.out
openswitcher.out					indi-3rdparty.indi-limesdr.out				antimicrox.out
openrgb.out						indi-3rdparty.indi-rtklib.out				android-udev-rules.out
openrgb-with-all-plugins.out				indi-3rdparty.indi-starbook-ten.out			alsa-utils.out
linuxKernel.packages.linux_6_12.openrazer.out		indi-3rdparty.indi-rolloffino.out			amazon-ec2-net-utils.out
linuxKernel.packages.linux_hardened.openrazer.out	indi-3rdparty.indi-ocs.out				amazon-ec2-utils.out
linuxKernel.packages.linux_6_13.openrazer.out		indi-3rdparty.indi-starbook.out				airspy.out
linuxKernel.packages.linux_5_4.openrazer.out		indi-3rdparty.indi-nightscape.out			acpilight.out

@r-vdp r-vdp merged commit be7b230 into NixOS:master May 20, 2025
20 of 21 checks passed
@nixpkgs-ci
Copy link
Contributor

nixpkgs-ci bot commented May 21, 2025

Successfully created backport PR for release-25.05:

@nixpkgs-ci nixpkgs-ci bot added the 8.has: port to stable This PR already has a backport to the stable release. label May 21, 2025
@LordGrimmauld
Copy link
Contributor Author

Uh, hold on - one thing that came to mind. Wouldn't we want to gate udev checking behind stdenv.hostPlatform.isLinux ? Should that check be in the hook or as lib.optionals wherever it is being used?

@LordGrimmauld
Copy link
Contributor Author

(currently drafting with optionals in the packages using the hook)

@LordGrimmauld LordGrimmauld mentioned this pull request May 21, 2025
13 tasks
@SuperSandro2000
Copy link
Member

Is there a way to easily inject this into many packages?

@LordGrimmauld
Copy link
Contributor Author

Is there a way to easily inject this into many packages?

Not yet, working on a treewide to add this to all packages providing udev rules. But i got distracted by the platform guarding issue, #409385 is basically a dependency to that treewide.

@SuperSandro2000
Copy link
Member

No hurry, I was just curious if there is a plan :)

@LordGrimmauld
Copy link
Contributor Author

WIP state is in #409564, finishing that will take a bit.

@LordGrimmauld
Copy link
Contributor Author

The treewide (#409564) is now ready to review. I got most packages for which it is viable to enable the hook.

@LordGrimmauld LordGrimmauld mentioned this pull request May 29, 2025
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

8.has: port to stable This PR already has a backport to the stable release. 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants