|
|
Subscribe / Log in / New account

The trouble with MODULE_LICENSE() in non-modules

By Jonathan Corbet
March 30, 2023
The kernel's hierarchical maintainer model works quite well from the standpoint of allowing thousands of developers to work together without (often) stepping on each others' toes. But that model can also make life painful for developers who are trying to make changes across numerous subsystems. Other possible source of pain include changes related to licensing or those where maintainers don't understand the purpose of the work. Nick Alcock has managed to hit all of those hazards together in his effort to perform what would seem like a common-sense cleanup of the kernel's annotations for loadable modules.

Discovering potential modules

Alcock did not set out to make tree-wide changes; he is, instead, working on adding some improved tracing features to the kernel. In order to provide a consistent interface to users, he needs to be able to discover code that, as a result of the kernel configuration, is built into the kernel, but which could also have been configured as a loadable module. He described the motivation as:

The reason: if your tracer or whatever has a distinct notation used by users for things in named modules, then you'd usually like to keep that notation the same if you choose to build something into the kernel that might otherwise be a module. Things that cannot be built as modules could just use the in-the-core-kernel notation unconditionally, because there's no way they can ever be found anywhere else: and users are likely to expect that. At least, when I broke it in DTrace years ago, I got complaints!

In other words, he is trying to treat kernel symbols in possibly modular code consistently regardless of whether that code is configured as a module in any given kernel build. In theory, this determination should not be hard to make; the kernel build process produces a file called modules.builtin that is described as listing "all modules that are built into the kernel". This file exists for a specific purpose: allowing the modprobe command to recognize a request to load a module that is already built into the kernel, do nothing in response, and complete successfully. It would seem that modules.builtin is exactly what Alcock is looking for, except that the contents of this file are not exactly as described.

Prior to the 5.6 release in early 2020, the build system would pass through each subsystem's Kconfig file to generate a list of potentially modular code that had been configured to be built into the kernel image directly. This mechanism worked, but it required a pass over the source tree, slowing the build process. So the maintainer of the kernel build system, Masahiro Yamada, decided to find a way to simplify and accelerate the generation of modules.builtin.

The solution that emerged was this commit, which took out the old machinery. In its place was a modification to one of the macros used to describe loadable modules. These macros have names like MODULE_AUTHOR(), MODULE_DESCRIPTION(), and MODULE_LICENSE(); each of them adds information to a special section in the compiled module that can be used by tools like modprobe. MODULE_LICENSE(), in particular, declares the license under which the module can be distributed; it is used primarily to control whether the module will have access to the GPL-only symbols within the kernel when it is loaded.

The MODULE_LICENSE() declaration is mandatory; a kernel module cannot be loaded without it. Since this declaration must appear in code that can be built as a module, Yamada decided to overload it as an indication that, indeed, a modular build is possible. So, in kernels starting with the 5.6 release, MODULE_LICENSE() adds an extra line to the compiled code indicating that it is part of a module; the build process can then scan the resulting object files for that line and collate the results into the new modules.builtin file.

The problem with this approach was noted by Yamada in the commit message: there is code in the kernel that contains MODULE_LICENSE() declarations, but which cannot be built as a module. Each of those occurrences causes a misleading line to be added to modules.builtin, describing a "built-in" module that is not, in fact, a module. For the purpose of allowing modprobe to recognize built-in modules, these false lines are not a problem; modprobe will simply ignore them. But, if one is trying to generate an accurate list of subsystems that truly can be built as modules, those lines are a problem indeed.

The beginning of the cleanup

In November 2022, Alcock posted a patch series that attempted to detect possible modules by adding a new build-time pass to create a new file called modules_thick.builtin, which would contain information that his work needs. Luis Chamberlain, the maintainer of the kernel's module loader, suggested using an augmented version of modules.builtin instead. That, in turn, brought the problem described above to light. Alcock eventually asked whether he should go through the kernel tree and remove all of the MODULE_* declarations found in non-modular code; Chamberlain answered "100% yes" and offered to send the resulting changes upstream via the modules tree.

Thus began the journey to clean up the kernel's module annotations. In early December, Alcock showed up with a patch set performing the removals; it also added some machinery to the build process to detect and warn about spurious MODULE_* declarations in an attempt to prevent the problem from coming back. Neither of those efforts went well.

Geert Uytterhoeven complained about the removal of the non-license information, saying that it is "useful information, in an easy-to-parse format" that should remain. He also said that some of the affected code might be made modular in the future, at which time that information would be needed. Alcock quickly agreed that only the MODULE_LICENSE() lines really needed to be deleted. But Arnd Bergmann, perhaps not understanding the actual problem being addressed, said that the license information, too, should remain if it isn't actively wrong. Christoph Hellwig suggested that the SPDX identifiers found in the kernel source should be used to generate the license information directly — a potentially nice idea but not a small task.

Meanwhile, Yamada rejected the build-system changes, saying "Please do not come back with this again. NACK." He added that "false-positives in modules.builtin should be OK", ignoring the discussion of why those false positives are problematic.

As a result, Alcock gave up on the build-system changes, and reduced his other patches to commenting out the spurious MODULE_LICENSE() entries. The first set, a toe-in-the-water exercise restricted to PCI drivers, was sent in February. PCI maintainer Bjorn Helgaas promptly complained that the subject lines did not match the PCI subsystem's conventions (a problem frequently encountered in tree-wide patch sets, and one that Alcock would hear about from multiple maintainers), and asked that the MODULE_LICENSE() lines be removed entirely rather than just commented out. Alcock duly started removing those lines thereafter.

Greg Kroah-Hartman responded to the second set by saying that all of the MODULE_* declarations should be removed if any are — matching what Alcock had initially tried to do and contradicting the advice he had gotten from other maintainers. Kroah-Hartman reiterated the complaint in response to the fifth set of removals, saying also that the kernel build system should be fixed rather than taking out the license declarations. In response to the sixth set, Chamberlain also suggested removing all of the module declarations; Alcock answered that, beyond the complaints he had gotten from others, some of those declarations (such as MODULE_DEVICE_TABLE()) have side effects that prevent their removal.

Kroah-Hartman also showed up in response to the sixth set, arguing more forcefully against its inclusion. He once again complained about removing only the MODULE_LICENSE() statements, and said:

Just change the macros to work properly in both cases, I can't believe this is all that hard as obviously all of the other macros work both ways, right? That should not require any kbuild changes.

Once again, this statement suggests a failure to understand the real problem that is being solved or the special semantics that Yamada had given to MODULE_LICENSE() in 5.6. There are no "both cases" for code that cannot be built as a module, and simply disabling MODULE_LICENSE() for a non-modular build of a subsystem would break the generation of modules.builtin entirely.

The conversation did not stop there, though; Kroah-Hartman insisted that "some of us disagree that this should be done at all" and asked that the license information that had been deleted so far be restored: "it is not a good idea to remove that if the file does not have a SPDX entry at the very least". The idea that a MODULE_LICENSE() line might actually define the license for a source file raises a number of concerns of its own, of course; deleting license information is generally frowned upon. But it is far from clear, as we will see, that MODULE_LICENSE() fills that role.

Removals removed

Be that as it may, Chamberlain, who had asked for this work to be done in the first place, and who had been applying the removals to the modules tree, summarily dropped them all, telling Alcock to "only re-submit only for files where the license is clear". Alcock responded with a license audit for the files in question, concluding that the situation is "a right mess". Some files have SPDX tags; others do not. Some of them have SPDX tags that contradict the MODULE_LICENSE() declaration in the same file. A MODULE_LICENSE() declaration, it would seem, is not a particularly reliable guide to the actual license attached to the source containing that declaration.

Alcock suggested that, perhaps, for files with unclear licensing, MODULE_LICENSE() could be turned into a new NONMODULE_LICENSE() macro, essentially returning to commenting out the declaration and preserving the information.

Kroah-Hartman answered that, actually, the SPDX lines and MODULE_LICENSE() cover different things: the former describes the license for the file in which it is found, while the latter provides the license for the built binary module. But the "license stuff" is "secondary", he said; the real problem remains the removal of just the MODULE_LICENSE() lines. He suggested again that Alcock should be "just stubbing out MODULE_LICENSE()" for non-modular builds — a "solution" that misses the problem entirely.

That message also said: "I'm confused why you picked the license line to trigger all of this". Alcock answered, clearly frustrated, that Yamada had attached the special meaning to MODULE_LICENSE(), and that Kroah-Hartman was "really objecting to the consequences of a years-old commit that I didn't write". He explained the whole story once again. As of this writing, that is where things stand; Kroah-Hartman has not responded to Alcock's explanation.

How all of this will be resolved is far from clear. Chamberlain is now advising Alcock to take on the project of adding proper SPDX lines to the relevant files that lack them as a step toward automatic generation of the module license declaration. This is a significant and fraught task; assigning a license to somebody else's code is not something to be done lightly. It's worth noting that Chamberlain sees this as a path toward removing all MODULE_LICENSE() declarations, of which there are over 11,000 in the kernel; that is not a small number of SPDX tags to check. A lot of work is being requested here that is orthogonal to Alcock's actual objectives.

Tree-wide changes are always painful to make; they tend to run afoul of the differing expectations of subsystem maintainers and, in any case, it is always hard to get a group of kernel maintainers to agree on anything. But the task gets significantly harder when multiple maintainers obstruct things without, seemingly, understanding the problem that is being solved. The tendency of maintainers to add requirements, such as figuring out what the licensing of kernel subsystems should really be, also does not help. It all adds up to a frustrating experience for a developer who is just trying to fix a problem so that he can get back to work on his real project. The kernel development process, as a whole, works quite well, but there are clearly situations where significant room for improvement exists.

Index entries for this article
KernelBuild system
KernelModules/Licensing


to post comments

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 30, 2023 17:11 UTC (Thu) by tbird20d (subscriber, #1901) [Link]

The kernel is a project with a single maintainer at the top. And it has an "ombudsman", in the form of Andrew Morton. Is there any indication that Linus or Andrew is aware of the situation?

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 30, 2023 20:24 UTC (Thu) by NYKevin (subscriber, #129325) [Link] (2 responses)

This whole story strikes me as the sort of thing that could be resolved in twenty minutes if all parties physically (or virtually) got in a room together and talked it out.

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 30, 2023 21:01 UTC (Thu) by nix (subscriber, #2304) [Link] (1 responses)

We did, at the last LPC. Everyone seemed happy -- then.

btw, there is actually a genuine problem with the old approach that Yamada removed in 2020: because it depends on redefining all CONFIG_ variables to contain an uppercase value, it falls foul of code scattered across the makefiles that relies on them being lowercase (to do things like building code into the kernel if something is built as a module, perhaps as some kind of shim). It's not one that anyone else ever noticed, because with no way to verify that the contents of modules.builtin were correct, it all went unnoticed in the flood of correct output. With *two* ways to generate the output (the old approach driven from tristate lines, and the new one from .modinfo), each could be validated against the other and a bunch of bugs fell out, unfortunately including 100+ extraneous MODULE_LICENSE lines...

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 30, 2023 21:15 UTC (Thu) by nix (subscriber, #2304) [Link]

The end goal of all this is to make it possible, when symbols are shown in trace output or specified as *input* to things like DTrace probes, to be sure that the symbol is unambiguously denoted even if it's inlined in hundreds of places, or a static function with a dozen definitions. This seems to me to be fairly important for tracer usage.

Here's the link to the LPC talk: <https://lpc.events/event/16/contributions/1379/>. This is now implemented, and I have a not-yet-shown-to-anyone patch making ftrace use it (for output, anyway). (perf is fighting back but I shall prevail.)

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 31, 2023 12:34 UTC (Fri) by buck (subscriber, #55985) [Link] (5 responses)

Our humble editor/author may have just hooked me with his dramatic telling, but it seems to me like Mr. Alcock is on a real hero's journey.

I hope his Supernatural Aid shows up soon.

Or suffice it to say: a lesser man like me would have succumbed already. Bless his fortitude

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 31, 2023 22:20 UTC (Fri) by nix (subscriber, #2304) [Link] (1 responses)

Don't heroes' journeys require the hero to *die* at least once, and then come back to life? I'm sure I can manage the first part. Not so sure about the second.

I also don't really want my mentor to die, which is very common in heroes' journeys.

(And... doesn't Jon count as supernatural aid? At the very least a spontaneously emitted LWN article of this nature sounds like it should be something of the kind. I don't want Jon to die either.)

The trouble with MODULE_LICENSE() in non-modules

Posted Mar 31, 2023 22:41 UTC (Fri) by mpr22 (subscriber, #60784) [Link]

The death and rebirth can be symbolic. (see: Jonah)

The trouble with MODULE_LICENSE() in non-modules

Posted Apr 13, 2023 3:18 UTC (Thu) by linuxrocks123 (subscriber, #34648) [Link] (2 responses)

"Lesser"? I mean no disrespect to Mr. Alcock, but I don't think refusing to suffer this type of repeated abuse by maintainers would make someone lesser. This article paints the kernel community as an extremely toxic working environment and the kernel maintainers as clueless jerks.

Shame on these jerks for not bothering to understand the problem. Shame on these jerks for giving orders to Mr. Alcock when they do not understand the problem. And, shame on these jerks for saying Mr. Alcock has to donate his time to solving a problem completely unrelated to the one he wants to solve just so that Mr. Alcock can have the privilege of having his donation of a solution the problem he wants to solve accepted by them.

I do not suffer fools, and I do not consider myself lesser for refusing to suffer fools. The kernel's maintainers have repeatedly acted like fools to Mr. Alcock, and he has had to suffer for it. If Mr. Alcock decides to tell the kernel community to shove it and use his talents somewhere else, I believe he would be in no way lesser for doing so.

I _DID_ walk away from the kernel community in the past. I wrote a mode for the network bonding driver that sent more packets on links that had higher capacity. I posted it to the appropriate mailing list, demands for revisions were made, and I said, "if I meet this subset of demands, would that be good enough to get this accepted?" Because, even 8 years ago, the kernel community had a reputation for trying to extract unrelated work out of developers who wanted to solve a particular problem, and I was wary of falling victim to that. I either got a "no", or no response, and then I asked if it would be okay to put a comment linking to the out-of-tree patch in the source since I wasn't willing to do the additional work they wanted. The answer? "No." Fine. It's still on my website if anyone wants it: http://moongate.ydns.eu/bond_mode_batman.patch

Setting boundaries is healthy. Kernel maintainers do not get to dictate how I spend my time. The module I wrote did what I needed for my use case, and, if the kernel maintainers did not want to accept my donation, I was perfectly free to walk away. So I did. The module is still in use, by me, for the purpose I wrote it for, although it is likely I will soon no longer need it due to advances in WiFi over the last 8 years.

Of course, when I walked away, I was warned how much trouble it would be to maintain the patch out-of-tree. No, dudes: I'm still running the same kernel on those systems that I was running 8 years ago. No maintenance required!

I was not treated _BADLY_ by the maintainers, but perhaps that was because I walked away early on rather than trying to do what they wanted. Perhaps, if I did do what they wanted, there would have been escalating demands. That's what I was afraid of, and that's certainly what happened to Mr. Alcock.

For the record

Posted Apr 13, 2023 13:38 UTC (Thu) by corbet (editor, #1) [Link] (1 responses)

The article was not intended to portray anybody as a "clueless jerk"; if you think an environment is toxic, you'll not improve it by throwing around insults like that.

The point of the article was that cross-tree changes are hard in a project of this size and structure, and that misunderstandings abound. My hope was that shining some light would help to resolve the situation; I'm not sure that I have been successful on that front, but time will tell.

For the record

Posted Apr 15, 2023 6:57 UTC (Sat) by oldtomas (guest, #72579) [Link]

> The article was not intended to portray anybody as a "clueless jerk"

I don't think it came over as that. On the contrary.

The situation illustrates one point, though: to fit one's contribution into a community work, there are extra costs. Sometimes (as in the current case) they seem outrageous, because processes or structures are at odds with that particular case.

Kudos to Mr. Alcock for sticking with it. And kudos to you for analysing things in such an even-headed way as ever. That's the only way to improve things.

Blaming stuff on others is the best way to stay "out of tree".

The trouble with MODULE_LICENSE() in non-modules

Posted Apr 6, 2023 8:45 UTC (Thu) by nim-nim (subscriber, #34454) [Link]

I may misunderstand the article, but since the original sin is overloading MODULE_LICENSE to mean two different things, would not it be possible to just copy all existing MODULE_LICENSE declarations into MODULE_BIKESHED lines, and then untangle the uses of MODULE_LICENSE and MODULE_BIKESHED so each of them serves a single purpose everyone understands and agrees on ?

That seems an easier sell than trying to complexify the effects of MODULE_LICENSE and then complain there is no maintainer understanding of buy-in for the new state of affairs.

It’s counterproductive to be overly subtle and clever when working with lots of people who have other things to do.

The trouble with MODULE_LICENSE() in non-modules

Posted Apr 25, 2023 14:06 UTC (Tue) by nix (subscriber, #2304) [Link]

Much thanks to Luis for pushing the less-contentious majority of these changes in in the end: <https://lore.kernel.org/linux-modules/ZEbkqq1tvm1WHVHw@bo...>. The nature of this is that it's increasingly useful the more is done: 100% coverage right away is definitely not required. So this is a huge step towards having this info always available.

(I have not given up, even though I've gone quiet: I'm just off doing other stuff in userspace for a while. I'll be back, since kallmodsyms still needs its cover letters and commit logs rendered comprehensible to people who aren't me and generally needs looking at again. And once that's done, there's CTF support...)


Copyright © 2023, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds