Failing to build out-of-tree kernel modules with MO= flag, attempting to modify /usr/src/kernels/<kernel>/Makefile

make: Entering directory '/usr/src/kernels/7.1.3-200.fc44.x86_64'
make[1]: Entering directory '/home/anish/97/kmod/build'
/bin/sh: line 1: /usr/src/kernels/7.1.3-200.fc44.x86_64/.tmp_Makefile: Permission denied
make[2]: *** [/usr/src/kernels/7.1.3-200.fc44.x86_64/Makefile:705: /usr/src/kernels/7.1.3-200.fc44.x86_64/Makefile] Error 1
make[1]: *** [/usr/src/kernels/7.1.3-200.fc44.x86_64/Makefile:248: __sub-make] Error 2

I have multiple projects that involve building a kernel module and all are failing on my newly installed Fedora Linux 44 (Sway). My config used to work fine on Arch Linux, and I think I must have also built it when I was trying Fedora Atomic. I can still build it in my source directory when not using MO= flag.

AI says it’s a bug. It shouldn’t write anything in the kernel source directory.

I then tried running as sudo and it replaced the Makefile at /usr/src/kernels/7.1.3-200.fc44.x86_64/Makefile with its wrapper. AI states that this is a serious bug. I re-installed kernel-devel.

Why is your script trying to write to /usr/src?

Your build should not need the src only the kernel-devel for headers I thought to build your module.

@barryascott My “script” can be just this command. Is this wrong?

make -C /lib/modules/$(uname -r)/build M=$PWD MO=$PWD/build/

I have not built a kernel module for a long time and do not remember the command to use.
Someone else may know.

But if I did want to know I would web search for the how too…

Why no response by anyone else?

Maybe no one who has seen your question knows the answer?

Did you search the web for how to build a kernel module?
Did it suggest using the same command you are using?

Seems like this a Kbuild issue. I updated my Arch Linux system and it doesn’t build. It definitely used to build before. I can still build, just without the MO flag, leading to all build artifacts being generated in the source directory of the kernel module.

The official docs state the usage of the MO flag.

($KDIR refers to the path of the kernel source directory, or the path of the kernel output directory if the kernel was built in a separate build directory.)

You can optionally pass MO= option if you want to build the modules in a separate directory.

make -C $KDIR M=$PWD [MO=$BUILD_DIR]

-C $KDIR

The directory that contains the kernel and relevant build artifacts used for building an external module. “make” will actually change to the specified directory when executing and will change back when finished.

M=$PWD

Informs kbuild that an external module is being built. The value given to “M” is the absolute path of the directory where the external module (kbuild file) is located.

MO=$BUILD_DIR

Specifies a separate output directory for the external module.

I can’t even build a simple hello world kernel module using the MO flag. Isn’t this correct?

obj-m += hello-1.o

PWD := $(CURDIR)

all:
	$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) MO=$(PWD)/build modules

clean:
	$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

$(PWD) should be ${PWD} or $PWD there I think, and probably similar for the other environment variables.

In general, $(foo) captures the output of command foo.

I think I tried but it doesn’t fix it. I can anyways see with the original command that the values of M and MO variables in the output log are being expanded to the correct path name.

edit - Trust LLMs a bit, they will pick up such syntax errors.

Even tried this.

make -f /lib/modules/$(uname -r)/build/Makefile M=$PWD MO=$PWD/build modules

You are expected to use akmods or DKMS like this:
Realtek 8125, huge packets loss at 2.5 Gbits - #2 by vgaetera

Why do I need DKMS for a simple Hello World kernel module? My projects are just standalone projects for learning. I don’t want them to auto build on every new kernel install.

I am literally using make or Makefile as per the guides. It definitely used to build before on early Linux 7 (or with the packages of that time). Did something change recently?

Because it works and you can study how it works by inspecting the logs.

Also it is best to learn the correct way for real life application, well tested and optimized for Fedora, with automation and scaling.

Here you go: How to insmod ko on Fedora 42 - #2 by vgaetera

Not if you are a kernel developer, you use the make command with the right Makefile and options as the OP is trying to do.

An end user would be expected to use akmods.

And the OP wants to build it like a kernel developer would.

In that case they should patch and build the kernel following the official documentation:

I don’t understand why I should be needing to use DKMS for learning to write kernel modules. It would be a better tool for actually distributing my module and having it persistently in use or active. I don’t plan to distribute or in a way that has to be persistent on a system. And isn’t DKMS a helpful tool rather than a hard requirement to compile a basic kernel module?

You have not addressed anything about what I am calling out a bug. The make command, as per the official guides, should work with the MO flag as I have stated. I am damn sure it used to work before. I could probably spin up a Debian instance to verify.

I don’t understand why the MO flag specifically is behaving this way. Without it, the module builds fine and all the build artifacts are in my source folder. All MO does is set the output directory. If I give it root privileges as it wants, it is replacing the kernel source’s Makefile with its wrapper. In which scenario does anything require to write to the installed kernel source’s Makefile?

What are you even talking about?

@vgaetera @barryascott

Fedora kept the 6.19 kernel and I installed it’s matching kernel-devel package. The MO flag works properly in this version.

This is clearly a Kbuild bug or a change in using it.

I am a newbie in Linux coding. I thought this forum had experienced people.

Kernel development has a small number of people that know it’s ins and outs. Edit: And they may not be active here.