Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow dkms to work in a chroot environment without /proc #485

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

akorn
Copy link

@akorn akorn commented Jan 28, 2025

I didn't author these changes; I'm just submitting the pull request (with the author's permission) in the hope that it can be merged with little or no discussion.

It's a fairly small and self-explanatory set of changes that, at least at first glance, shouldn't alter existing behaviour, just make dkms as a whole more robust by not requiring /proc to be mounted for it to work.

@scaronni
Copy link
Collaborator

@akorn I'm all for the change, but the tests are failing, can you have a look? Thanks.

If the change requires changes to the tests, please provide those as well.

@akorn
Copy link
Author

akorn commented Jan 31, 2025

@scaronni, with my latest commit the tests mostly succeed, except this one:

Building and installing the noisy test module
--- test_cmd_expected_output.log        2025-01-31 17:29:58.377860489 +0000
+++ test_cmd_output.log 2025-01-31 17:30:09.022193710 +0000
@@ -17,9 +17,7 @@
 pre_build: line 3
 pre_build: line 4/stderr
 pre_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Building module(s)... done.
 Signing module /var/lib/dkms/dkms_noisy_test/1.0/build/dkms_noisy_test.ko
 Running the post_build script:
@@ -29,9 +27,7 @@
 post_build: line 3
 post_build: line 4/stderr
 post_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Running the pre_install script:
 /var/lib/dkms/dkms_noisy_test/1.0/source/script.sh pre_install
 pre_install: line 1
Error: unexpected output from: dkms install -k 6.11.10-amd64 -m dkms_noisy_test -v 1.0

It seems that where the test expects make clean to fail, it now succeeds. :)

Is that really a problem?

If yes, I don't know how to fix it (i.e. break it again); I couldn't immediately understand how the tests even work.

@scaronni scaronni requested a review from anbe42 February 4, 2025 08:51
@akorn
Copy link
Author

akorn commented Feb 4, 2025

@anbe42, you wrote that noisy test that now succeeds instead of failing. Can you help a bit here? Why/how is make clean supposed to fail? And do you have an idea why it succeeds in my chroot instead?

@anbe42
Copy link
Collaborator

anbe42 commented Feb 4, 2025

Do you have the same kernel running on the host and installed in the chroot? Try a different kernel in the chroot.

Usually host and chroot have different kernels (as it happens in all the CI scenarios) and the wrong 'make clean' command picks the wrong kernel (the one from the host). IIRC I had some checks for this issue, but maybe not in this specific test case.

@akorn
Copy link
Author

akorn commented Feb 4, 2025

Do you have the same kernel running on the host and installed in the chroot? Try a different kernel in the chroot.

If I only have a different kernel in the chroot, the tests fail much sooner:

Using kernel 6.11.10-amd64/x86_64
Checking module compression ...
grep: /lib/modules/6.11.10-amd64/build/.config: No such file or directory
config: 
files: 
Expected extension: (none)
Preparing a clean test environment
Test that there are no dkms modules installed
Test framework file hijacking
*** Testing dkms on a regular module
Adding the test module by version (expected error)
Adding the test module by directory
Adding the test module again (expected error)
Adding the test module by version (expected error)
Building the test module
Error: command 'dkms build -k 6.11.10-amd64 -m dkms_test -v 1.0' returned status 21 instead of expected 0

Error! Your kernel headers for kernel 6.11.10-amd64 cannot be found at /lib/modules/6.11.10-amd64/build or /lib/modules/6.11.10-amd64/source.
Please install the linux-headers-6.11.10-amd64 package or use the --kernelsourcedir option to tell DKMS where it's located.

If I have both the same and a newer kernel, the testsuite fails later:

Running dkms autoinstall with multiple modules
--- test_cmd_expected_output.log        2025-02-04 12:33:31.706315727 +0000
+++ test_cmd_output.log 2025-02-04 12:34:00.402266447 +0000
@@ -24,9 +24,7 @@
 pre_build: line 3
 pre_build: line 4/stderr
 pre_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Building module(s)... done.
 Signing module /var/lib/dkms/dkms_noisy_test/1.0/build/dkms_noisy_test.ko
 Running the post_build script:
@@ -36,9 +34,7 @@
 post_build: line 3
 post_build: line 4/stderr
 post_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Running the pre_install script:
 /var/lib/dkms/dkms_noisy_test/1.0/source/script.sh pre_install
 pre_install: line 1
Error: unexpected output from: dkms autoinstall -k 6.11.10-amd64

And if I have an older, the same, and a newer kernel:

*** Testing more dkms features
Adding test module with patches
Building and installing the test module with patches
Unbuilding the test module with patches
Adding test module with pre/post scripts
Building and installing the test module with pre/post scripts
Unbuilding the test module with pre/post scripts
Adding noisy test module
Building and installing the noisy test module
Sign command: /lib/modules/6.11.10-amd64/build/scripts/sign-file
Signing key: /var/lib/dkms/mok.key
Public certificate (MOK): /var/lib/dkms/mok.pub

applying patch patch2.patch...patching file Makefile
patching file dkms_noisy_test.c
 done.
applying patch patch1.patch...patching file Makefile
Hunk #1 succeeded at 3 (offset 2 lines).
patching file dkms_noisy_test.c
Hunk #1 succeeded at 18 (offset 2 lines).
 done.
Running the pre_build script:
/var/lib/dkms/dkms_noisy_test/1.0/build/script.sh pre_build
pre_build: line 1
pre_build: line 2/stderr
pre_build: line 3
pre_build: line 4/stderr
pre_build: line 5
Cleaning build area... done.
Building module(s)... done.
Signing module /var/lib/dkms/dkms_noisy_test/1.0/build/dkms_noisy_test.ko
Running the post_build script:
/var/lib/dkms/dkms_noisy_test/1.0/build/script.sh post_build
post_build: line 1
post_build: line 2/stderr
post_build: line 3
post_build: line 4/stderr
post_build: line 5
Cleaning build area... done.
Running the pre_install script:
/var/lib/dkms/dkms_noisy_test/1.0/source/script.sh pre_install
pre_install: line 1
pre_install: line 2/stderr
pre_install: line 3
pre_install: line 4/stderr
pre_install: line 5
Installing /lib/modules/6.11.10-amd64/updates/dkms/dkms_noisy_test.ko.xz
Running the post_install script:
/var/lib/dkms/dkms_noisy_test/1.0/source/script.sh post_install
post_install: line 1
post_install: line 2/stderr
post_install: line 3
post_install: line 4/stderr
post_install: line 5
Running depmod... done.
Unbuilding the noisy test module
*** Testing multiple dkms modules
Adding test module with dependencies
Adding build-exclusive test module
Adding noautoinstall test module
Adding test module
Running dkms autoinstall with multiple modules
--- test_cmd_expected_output.log        2025-02-04 12:44:48.733996280 +0000
+++ test_cmd_output.log 2025-02-04 12:45:17.330355693 +0000
@@ -24,9 +24,7 @@
 pre_build: line 3
 pre_build: line 4/stderr
 pre_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Building module(s)... done.
 Signing module /var/lib/dkms/dkms_noisy_test/1.0/build/dkms_noisy_test.ko
 Running the post_build script:
@@ -36,9 +34,7 @@
 post_build: line 3
 post_build: line 4/stderr
 post_build: line 5
-Cleaning build area...(bad exit status: 2)
-Failed command:
-make clean
+Cleaning build area... done.
 Running the pre_install script:
 /var/lib/dkms/dkms_noisy_test/1.0/source/script.sh pre_install
 pre_install: line 1
Error: unexpected output from: dkms autoinstall -k 6.11.10-amd64

It doesn't seem like I can satisfy this particular test. @anbe42, any suggestions?

@akorn
Copy link
Author

akorn commented Feb 6, 2025

@scaronni meanwhile, can you perhaps rerun the tests in the official test environment? Who knows, they might succeed there. :) Thanks!

@anbe42
Copy link
Collaborator

anbe42 commented Feb 7, 2025

The applied substitution does not produce identical results if it involves empty command output:

#!/bin/bash

f()
{
echo foo
}

g()
{
:
}

while read line; do
        echo "< <(f): '$line'"
done < <(f)
while read line; do
        echo "< <(g): '$line'"
done < <(g)

while read line; do
        echo '<<< "$(f)":' "'$line'"
done <<< "$(f)"
while read line; do
        echo '<<< "$(g)":' "'$line'"
done <<< "$(g)"
< <(f): 'foo'
<<< "$(f)": 'foo'
<<< "$(g)": ''

This breaks e.g. 'autoinstall'

*** Testing dkms autoinstall/kernel_{postinst/prerm}, dkms_autoinstaller
Testing without modules and without headers
 Running dkms autoinstall
Error: command 'dkms autoinstall -k 6.12.8-amd64-noheaders' returned status 1 instead of expected 0
/home/anbe/deb-src/dkms/dkms/dkms: line 2535: latest: bad array subscript
/home/anbe/deb-src/dkms/dkms/dkms: line 2537: latest[$m]: bad array subscript

Please rebase your branch on master.

@scaronni
Copy link
Collaborator

@akorn i've also fixed the issues with the fedora rawhide containers, so if you rebase on master at least you would get working tests.

@akorn
Copy link
Author

akorn commented Feb 10, 2025

The applied substitution does not produce identical results if it involves empty command output:

I know. I was hunting for occurrences where this mattered and already resolved some of them in commits 6801dc1 and 5f9f3c0, but not all (not being able to run the tests myself doesn't help -- I guess I'll just disable the noisy one locally).

*** Testing dkms autoinstall/kernel_{postinst/prerm}, dkms_autoinstaller
Testing without modules and without headers
Running dkms autoinstall
Error: command 'dkms autoinstall -k 6.12.8-amd64-noheaders' returned status 1 instead of expected 0
/home/anbe/deb-src/dkms/dkms/dkms: line 2535: latest: bad array subscript
/home/anbe/deb-src/dkms/dkms/dkms: line 2537: latest[$m]: bad array subscript

I'll deal with this soon.

Please rebase your branch on master.

Done.

@akorn
Copy link
Author

akorn commented Feb 10, 2025

@scaronni, can you rerun the tests? They succeed for me now (except the noisy one, but I don't think that's related to my changes).

@scaronni
Copy link
Collaborator

Running, sorry for the delay.

@anbe42
Copy link
Collaborator

anbe42 commented Feb 11, 2025

it now works for me in my Debian test setup

I'll try to test without /proc, too

@scaronni: is it possible to add one test (any distribution, prefereably one utilizing the weak module code paths) with /proc unmounted to the CI matrix?

@akorn: please rebase (git rebase) on master, don't merge master into the topic branches

@scaronni
Copy link
Collaborator

@scaronni: is it possible to add one test (any distribution, prefereably one utilizing the weak module code paths) with /proc unmounted to the CI matrix?

I think we can just add an extra tag in the table here: https://github.com/dell/dkms/blob/master/.github/workflows/tests.yml#L15

And then trigger a specific task in the tests than unmouns /proc. Maybe even better, shall we just add a test that unmounts /proc for all distributions in run_test.sh?

@akorn: please rebase (git rebase) on master, don't merge master into the topic branches

Yes please, do a clean rebase (Fast Forward merge), no merge commits please. Besides this, I think it's fine for merging once corrected. Thanks.

@akorn akorn force-pushed the chroot-no-proc branch 2 times, most recently from 26afe79 to 57e045b Compare February 12, 2025 13:31
@scaronni
Copy link
Collaborator

@anbe42 I'm fine with merging as soon as the tests pass. Do you agree?

Copy link
Collaborator

@anbe42 anbe42 left a comment

Choose a reason for hiding this comment

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

In bash we can use [[ $var ]] to check for non-empty values. While it is not being used consistently, [[ -n "$var" ]] is less common (8 vs. 13 occurrences). So I'd prefer the shorter form.

@akorn
Copy link
Author

akorn commented Feb 13, 2025

In bash we can use [[ $var ]] to check for non-empty values. While it is not being used consistently, [[ -n "$var" ]] is less common (8 vs. 13 occurrences). So I'd prefer the shorter form.

Should I make this change everywhere for consistency, or just in the new lines that I'm adding?

@anbe42
Copy link
Collaborator

anbe42 commented Feb 13, 2025

Should I make this change everywhere for consistency, or just in the new lines that I'm adding?

only in your new bits in order not to interfere with the ongoing shellcheck changes (#492)

@akorn
Copy link
Author

akorn commented Feb 13, 2025

Should I make this change everywhere for consistency, or just in the new lines that I'm adding?

only in your new bits in order not to interfere with the ongoing shellcheck changes (#492)

Done, I think.

@anbe42
Copy link
Collaborator

anbe42 commented Feb 13, 2025

It seems that where the test expects make clean to fail, it now succeeds. :)

I finally managed to reproduce that and I'm currently testing a fix ...

@anbe42
Copy link
Collaborator

anbe42 commented Feb 13, 2025

it now works for me in my Debian test setup

I'll try to test without /proc, too

need to try that again, my machine crashed last night ... hopefully unrelated to that test ;-)

zeha and others added 13 commits February 14, 2025 16:05
In do_status_weak(), the previous code that relied on "< <" didn't run the
loop when `module_status_weak()` returned failure.

The new code, with "<<<", ignores the return status of
`module_status_weak()` and only uses its output, even if it's empty.

This change exits the `while` loop in `do_status_weak()` if
`module_status_weak()` returned nothing.

Similar changes may be necessary elsewhere, but let's see if this fixes the
test.
In `setup_kernel_arches()`, we try to determine whether the architecture
should be `ia32e`, based on some heuristics involving /proc/cpuinfo.

This change allows the code to continue if `/proc/cpuinfo` doesn't exist,
e.g. because we're in a chroot and `/proc` isn't mounted.

In chroot situations where this heuristic architecture detection is expected
to work (which I assume to be rare), a faux `/proc/cpuinfo` file should be
created before calling `dkms`, e.g.  by copying it from the host's real
`/proc`.

Since `dkms` would have just failed in such chroot environments before, this
change still results in an improvement; the code can be refined later if
necessary.
The shift from the `< <(cmd)` idom to `<<<"$(cmd)"` which is needed to work
without /proc being mounted has the unfortunate side effect that the exit
status of `cmd` is ignored where it wasn't before.

This can cause statements that previously always had valid input to be
called on empty strings.

One such occurrence was in `setup_kernels_arches()`, which, among other
things, populates the `kernelver` array; after the `<<<` change, this array
could contain an empty string as an element.

This commit adds a sanity check to make sure we don't pretend there is a
kernel whose version number is the empty string.
For me, the tests succeed now, but maybe not all of these changes were necessary.
We were testing `[[ -n "$status" ]]` twice; go with the more
explicit/readable `|| continue` version like everyhwere else.
(Only in new lines added by the chroot-no-proc branch.)
Copy link
Collaborator

@anbe42 anbe42 left a comment

Choose a reason for hiding this comment

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

I think you can squash most of your fixup commits together. The /proc/cpuinfo check should stay separate. If I'm not mistaken, everything else deals with skipping the empty lines introduced by using the alternate idiom.

Please wait with rebasing for #492 (the shellcheck changes) being merged, that may cause some conflicts and may require some further reworking.

I've just tried adding a umount /proc && run_tests.sh test to the Debian package and tested your branch with it. Didn't explode ;-)

@@ -384,7 +384,7 @@ setup_kernels_arches()
local i
i=0
while read line; do
[[ -n "$line" ]] || continue
[[ "$line" ]] || continue
Copy link
Collaborator

Choose a reason for hiding this comment

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

please use unquoted [[ $line ]]

@akorn
Copy link
Author

akorn commented Feb 17, 2025

I think you can squash most of your fixup commits together. The /proc/cpuinfo check should stay separate. If I'm not mistaken, everything else deals with skipping the empty lines introduced by using the alternate idiom.

Yes, I think so too.

Please wait with rebasing for #492 (the shellcheck changes) being merged, that may cause some conflicts and may require some further reworking.

Roger that, standing by.

I've just tried adding a umount /proc && run_tests.sh test to the Debian package and tested your branch with it. Didn't explode ;-)

That's good news -- I think I fixed almost all bugs that could have led to actual explosions. :)

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

Successfully merging this pull request may close these issues.

4 participants