Skip to content

Conversation

flodavid
Copy link

I created scripts to automate the signing and installation steps required on systems with Secure Boot enabled

@flodavid flodavid changed the title xpadneo, installer: Add scripts that sign the module for Secure Boot installer: Add scripts that sign the module for Secure Boot Oct 11, 2025
@flodavid flodavid changed the title installer: Add scripts that sign the module for Secure Boot Add scripts that sign the module for Secure Boot Oct 11, 2025
@kakra kakra added the 0 | type: enhancement New feature or request label Oct 12, 2025
@kakra kakra added this to the v0.10 milestone Oct 12, 2025
@kakra
Copy link
Collaborator

kakra commented Oct 12, 2025

Thanks, this look useful. I'll first let Copilot do a review. I'll look into this soon, I hope. I'm currently lacking some time.

@kakra kakra requested a review from Copilot October 12, 2025 12:09
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for signing kernel modules for Secure Boot compatibility by introducing two automated scripts. The scripts handle the complete workflow of generating signing keys, importing them into the MOK (Machine Owner Key) system, and signing the hid-xpadneo kernel module.

Key changes:

  • Added automated signing and installation scripts for both DKMS and generic installations
  • Implemented MOK key generation and certificate management for Secure Boot
  • Added documentation explaining how to use the signing scripts

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 12 comments.

File Description
sign_and_install.sh DKMS-specific script that automates key generation, MOK enrollment, and module signing for Secure Boot
hid-xpadneo/sign_and_install_generic.sh Generic installation script with similar functionality but uses direct make commands instead of DKMS
docs/README.md Documentation update explaining how to use the new signing scripts

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@flodavid
Copy link
Author

I addressed Copilot feedback and did some small improvements

Copy link
Collaborator

@kakra kakra left a comment

Choose a reason for hiding this comment

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

Mostly nitpicks. I appreciate your work but I have to admit that I did just a quick scan through your changes and didn't test it yet. That's because I don't run a secure boot system here. I'd need to setup a VM or container - probably with different distributions.

If that works, tho, I'm pretty confident I can use that as a template to make my bare metal system secureboot. So, thanks already here. :-)

@flodavid
Copy link
Author

I am no expert on this topic so I am not really sure about anything to be honest. I did not do a ton of research. The installation failed for me so I adapted a script that I found for another project and figured that it could be useful for other people too

@kakra
Copy link
Collaborator

kakra commented Oct 14, 2025

Given the discussion, I'm guessing this script is mainly used for manual installation, not for the module being managed by dkms? Tho, your doc patches say "if you use dkms...". I think we should check how other dkms-managed modules handle that.

@flodavid flodavid marked this pull request as draft October 15, 2025 21:48
@flodavid
Copy link
Author

flodavid commented Oct 15, 2025

Given the discussion, I'm guessing this script is mainly used for manual installation, not for the module being managed by dkms? Tho, your doc patches say "if you use dkms...". I think we should check how other dkms-managed modules handle that.

It turns out I was doing it wrong. I was signing AFTER dkms has installed the module, using custom MOK, which prevented auto rebuilds. But in the build output, there is these lines:

Sign command: /usr/bin/kmodsign
Signing key: /var/lib/shim-signed/mok/MOK.priv

Indeed dkms uses shim-signed, which already creates MOK for the machine, they just need to be enrolled. I updated the script to handle that, and removed the custom signing step (I kept the one creating the MOK if it is missing).
There is now this additional log during the build, if the shim-signedkey is enrolled:

Signing module /var/lib/dkms/hid-xpadneo/v0.9-228-g2d516d3-dirty/build/src/hid-xpadneo.ko

@kakra
Copy link
Collaborator

kakra commented Oct 16, 2025

Sounds promising, I really appreciate it but will need to find some spare time to test it in a VM.

@flodavid
Copy link
Author

I simplified the script and improved the process again, by using update-secureboot-policy which manages key generation and enrolment.
I also added the set -e option

Copy link
Collaborator

@kakra kakra left a comment

Choose a reason for hiding this comment

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

Good cleanup but there are some issues.

Makefile Outdated
echo "Skipping key creation"
endif
@$(KSRC)/scripts/sign-file sha256 MOK.priv MOK.der hid-xpadneo.ko
@sudo update-secureboot-policy --new-key
Copy link
Collaborator

Choose a reason for hiding this comment

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

The Makefile should not call sudo, especially it should not do so hidden, and it should not run by surprise (e.g., you may have unlocked sudo before, and then it would run without asking for passwords). This also makes no sense because modprobe requires sudo but doesn't use it here. I'd suggest to rather add a guard [ "$(id -u)" = "0" ] || { echo >&2 "need to run with sudo"; exit 1; }.

There are exceptions to this rule but this one is obviously not it.

else
if mokutil --sb-state | grep -q "SecureBoot enabled"
then if ! grep -q "hid_xpadneo" /proc/modules && info "hid_xpadneo is loaded"
then if ! grep -q "hid_xpadneo" /proc/modules
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will fail on systems which linked xpadneo statically into the kernel. Check for [ -d /sys/module/hid_xpadneo ], it will tell you if the driver is present in the kernel. OTOH, if xpadneo is statically linked into the kernel, you won't have to try signing it in the first place. ;-)

Copy link
Author

Choose a reason for hiding this comment

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

I now look into /sys/module/hid_xpadneo. I will try to to add a check to see if the module should not be signed because it is statically linked into the kernel

Copy link
Collaborator

Choose a reason for hiding this comment

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

modinfo will return (builtin) on the filename line if it is builtin, e.g. I have btrfs built into the kernel:

# modinfo btrfs
name:           btrfs
filename:       (builtin)
...

But if a module is unknown, it will return an error:

# modinfo unknown || echo "exit code: $?"
modinfo: ERROR: Module unknown not found.
exit code: 1

Copy link
Author

@flodavid flodavid Oct 20, 2025

Choose a reason for hiding this comment

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

Now that I think about it, I do not think I need to worry about that, since, as you said, there is no need to sign it if the module is statically linked. And I already skip the signing & install when the module is loaded (as it should be if statically linked I guess)

Makefile Outdated
@$(KSRC)/scripts/sign-file sha256 $(SHIM_MOK_DIR)/MOK.priv $(SHIM_MOK_DIR)/MOK.der $(LIB_PREFIX)/hid-xpadneo.ko
modprobe hid-xpadneo

sign-install: all install sign
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to pull in all here, install already pulls build.

Makefile Outdated
@sudo update-secureboot-policy --new-key
@sudo update-secureboot-policy --enroll-key
@$(KSRC)/scripts/sign-file sha256 $(SHIM_MOK_DIR)/MOK.priv $(SHIM_MOK_DIR)/MOK.der $(LIB_PREFIX)/hid-xpadneo.ko
modprobe hid-xpadneo
Copy link
Collaborator

Choose a reason for hiding this comment

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

The recipe says "sign" - don't modprobe. Especially, modprobe won't reload the module, so the outcome is not deterministic.

Makefile Outdated
rm -f $(MODPROBE_CONFS:%=$(PREFIX)$(ETC_PREFIX)/modprobe.d/%)
rmdir --ignore-fail-on-non-empty -p $(PREFIX)$(ETC_PREFIX)/modprobe.d $(PREFIX)$(ETC_PREFIX)/udev/rules.d $(PREFIX)$(DOC_PREFIX)

sign:
Copy link
Collaborator

Choose a reason for hiding this comment

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

You need $(LIB_PREFIX)/hid-xpadneo.ko here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

You also need $(SHIM_MOK_DIR)/MOK.priv $(SHIM_MOK_DIR)/MOK.der...

Copy link
Collaborator

@kakra kakra left a comment

Choose a reason for hiding this comment

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

I wonder if signing with the Makefile is even worth it. It should be handle by dkms. If you need this for development, maybe move it to hid-xpadneo/Makefile instead? That file also allows usage of sudo for developer convenience. I'm using that to rebuild and reload my module during development like this:

make -C hid-xpadneo reinstall

Makefile Outdated
rm -f $(MODPROBE_CONFS:%=$(PREFIX)$(ETC_PREFIX)/modprobe.d/%)
rmdir --ignore-fail-on-non-empty -p $(PREFIX)$(ETC_PREFIX)/modprobe.d $(PREFIX)$(ETC_PREFIX)/udev/rules.d $(PREFIX)$(DOC_PREFIX)

sign:
Copy link
Collaborator

Choose a reason for hiding this comment

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

You also need $(SHIM_MOK_DIR)/MOK.priv $(SHIM_MOK_DIR)/MOK.der...

Makefile Outdated
sign:
@sudo update-secureboot-policy --new-key
@sudo update-secureboot-policy --enroll-key
@$(KSRC)/scripts/sign-file sha256 $(SHIM_MOK_DIR)/MOK.priv $(SHIM_MOK_DIR)/MOK.der $(LIB_PREFIX)/hid-xpadneo.ko
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you add the dependency for the sign recipe, you can use $< to reference the first dependency aka $(LIB_PREFIX)/hid-xpadneo.ko.

@flodavid flodavid force-pushed the signing-module-scripts branch from 73fd8cd to 6ef9bf6 Compare October 19, 2025 19:33
kakra added a commit to kakra/xpadneo that referenced this pull request Oct 19, 2025
`dkms remove` may fail because a previous installation has been broken
or tampered with. This will cause the remaining uninstallation to fail.
Fix this by logging that we proceed anyways.

Reported-by: @flodavid
Link: atar-axis#563
Signed-off-by: Kai Krakow <[email protected]>
kakra added a commit to kakra/xpadneo that referenced this pull request Oct 19, 2025
`dkms remove` may fail because a previous installation has been broken
or tampered with. This will cause the remaining uninstallation to fail.
Fix this by logging that we proceed anyways.

Reported-by: flodavid <[email protected]>
Link: atar-axis#563
Signed-off-by: Kai Krakow <[email protected]>
@flodavid
Copy link
Author

Thank you for your feedback and advices, that’s appreciated.

If think the dkms process is almost complete.

I am still working on the generic install. I am not sure about the use of the PEM certificate and its password. I will also try to have good signing rules in the makefile and maybe remove some bash functions to use those instead.

I have a problem on my system though. I guess I have firmware 5.x since the module is not working without uhid. Since the scripts try to load it, it works when I’m running them, but I have to run modprobe uhid on every restart for the driver to work. Do you know if it would be possible to solve this using modprobe softdep, weakdep, or something else ?

kakra added a commit to kakra/xpadneo that referenced this pull request Oct 19, 2025
`dkms remove` may fail because a previous installation has been broken
or tampered with. This will cause the remaining uninstallation to fail.
Fix this by logging that we proceed anyways.

Suggested-by: flodavid <[email protected]>
Link: atar-axis#563
Signed-off-by: Kai Krakow <[email protected]>
@kakra
Copy link
Collaborator

kakra commented Oct 19, 2025

I have a problem on my system though. I guess I have firmware 5.x since the module is not working without uhid

I'm not sure how we should properly handle that. It is expected that bluez loads uhid if it is needed. xpadneo is not responsible to do that, we are a HID user, not a HID provider. So I think you should report it to your distribution, maybe they should link uhid statically into the kernel, or add a dependency.

Until then, you could just run:

# always load uhid on boot (requires systemd)
echo "uhid" | sudo tee -a /etc/modules-load.d/99-local.conf

# OR: load uhid with xpadneo (untested)
echo "softdep hid-xpadneo pre: uhid" | sudo tee -a /etc/modprobe.d/99-xpadneo-local.conf

# ALTERNATIVE: load uhid with bluetooth (untested, probably preferred)
echo "softdep bluetooth pre: uhid" | sudo tee -a /etc/modprobe.d/99-bluetooth-uhid.conf

If uhid-related reports keep popping up, we might need to add the latter into xpadneo, tho, I still think, distributions should add that to the standard kernel if they provide bluez with BLE support (or make the bluez service load the module). BLE input devices cannot be used without uhid. Thus, there's no point in adding a softdep to each driver which in theory might maybe support a Bluetooth HID device...

EDIT: I added another alternative.

@flodavid
Copy link
Author

flodavid commented Oct 20, 2025

Thanks. I tried softdep hid-xpadneo in "99-xpadneo-local.conf" and I had already tried in "/etc/modprobe.d/xpadneo.conf", but it did not work. The one who does is softdep bluetooth in "99-bluetooth-uhid.conf".

What's strange is that I have no vibration when the controller is connected, even though there is ff_connect_notify=1 in "/etc/modprobe.d/99-xpadneo-options.conf". It worked before.
EDIT: retried it and it worked this time. Strange

@kakra
Copy link
Collaborator

kakra commented Oct 21, 2025

What's strange is that I have no vibration when the controller is connected, even though there is ff_connect_notify=1

This can happen if xpadneo needs to bind lazily to the device via udev rules - it may not have worked during the first connection, and then only on second connect, it will work (and that means, also uhid is present, because we need that to speak to the controller). If xpadneo is already loaded, it will bind immediately and automatically.

You should see a difference in dmesg for both tries - if you can still replicate it...

The one who does is softdep bluetooth in "99-bluetooth-uhid.conf".

Which proves that the driver providing the HID bus has to load it - which is bluez. xpadneo is only a HID consumer. It doesn't even know about BT. Most likely, bluez user-space should probably trigger loading uhid as soon as an BLE input device connects, loading just a bluetooth module isn't technically the correct trigger to load uhid.

Actually, there's a race condition with softdep hid-xpadneo: When loading of xpadneo is triggered by udev, the device has already been enumerated on the HID bus by bluez - so loading uhid now will miss the initial HID handshake of the controller, and thus it probably doesn't work properly (or only on second try). That is, if xpadneo is triggered at all by udev... Without uhid, the udev rules may not even see the HID device.

If you asked me, uhid should be built statically into the kernel by your distribution. It's a needed core driver, not optional. And not only needed by bluez but also by some input device emulators (tho, I think Steam Input uses uinput instead).

kakra added a commit to kakra/xpadneo that referenced this pull request Oct 21, 2025
The system should trigger loading of the `uhid` module when `bluetooth`
is loaded to properly support BLE devices which provide the HID bus
from user-space through bluez.

This may still leave a gap for a race-condition if both `bluetooth` and
the BLE device appear at the same time. `uhid` should be present before
any device even connects from user-space, otherwise `hid-xpadneo` may
not see the HID bus early enough.

I'm unsure if we also should provide `weakdep` to trigger inclusion of
`uhid` into initrd - but since Xbox controllers are not critical input
devices during early boot, this is probably not our business. OTOH,
`softdep` may already trigger inclusion on its own (untested).

Link: atar-axis#563 (comment)
Signed-off-by: Kai Krakow <[email protected]>
kakra added a commit to kakra/xpadneo that referenced this pull request Oct 21, 2025
The system should trigger loading of the `uhid` module when `bluetooth`
is loaded to properly support BLE devices which provide the HID bus
from user-space through bluez.

This may still leave a gap for a race-condition if both `bluetooth` and
the BLE device appear at the same time. `uhid` should be present before
any device even connects from user-space, otherwise `hid-xpadneo` may
not see the HID bus early enough.

I'm unsure if we also should provide `weakdep` to trigger inclusion of
`uhid` into initrd - but since Xbox controllers are not critical input
devices during early boot, this is probably not our business. OTOH,
`softdep` may already trigger inclusion on its own (untested).

Hint: This feels wrong because xpadneo is the HID consumer, not the HID
provider. We should not need to do that. But it prevents bug reports
from users in the future.

Link: atar-axis#563 (comment)
Signed-off-by: Kai Krakow <[email protected]>
kakra added a commit to kakra/xpadneo that referenced this pull request Oct 21, 2025
The system should trigger loading of the `uhid` module when `bluetooth`
is loaded to properly support BLE devices which provide the HID bus
from user-space through bluez.

This may still leave a gap for a race-condition if both `bluetooth` and
the BLE device appear at the same time. `uhid` should be present before
any device even connects from user-space, otherwise `hid-xpadneo` may
not see the HID bus early enough.

I'm unsure if we also should provide `weakdep` to trigger inclusion of
`uhid` into initrd - but since Xbox controllers are not critical input
devices during early boot, this is probably not our business. OTOH,
`softdep` may already trigger inclusion on its own (untested).

Hint: This feels wrong because xpadneo is the HID consumer, not the HID
provider. We should not need to do that. But it prevents bug reports
from users in the future.

Tested-by: flodavid <[email protected]>
Link: atar-axis#563 (comment)
Signed-off-by: Kai Krakow <[email protected]>
@flodavid flodavid force-pushed the signing-module-scripts branch from 938f39b to 8c68f33 Compare October 22, 2025 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0 | type: enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants