Kernel module compatibility with kernel recompiled with new patch - linux

I would like to know if a Linux Kernel Module can be used with a Linux Kernel version of a higher patch number (last number in the version) than the kernel was compiled against.
Take the following example:
You are currently using Linux 4.14.75 for an ARM target
I give you an RPM containing an application and kernel module that work together. The module was compiled against the 4.14.75 kernel. The module is loaded with insmod by the application.
A security concern arises and you update your target's kernel to 4.14.100.
Given this situation, will the kernel module in the RPM I gave you work with the new kernel?Is it possible to compile a kernel once and have it be compatible with all 4.14 kernels?
I am NOT asking if depmod/modprobe will work or if it is good practice.

"Is it possible to compile a kernel once and have it be compatible with all 4.14 kernels?"
If security updates and backports do not break anything, maybe.
However there is no stable Kernel API/ABI in the Kernel.
Just userland API/ABIs are stable.
https://www.phoronix.com/scan.php?page=news_item&px=Linux-Kernel-Stable-API-ABI
https://github.com/torvalds/linux/blob/master/Documentation/process/stable-api-nonsense.rst
Here a post to automatically check, if any API/ABI to userland will break/breaks:
Linux kernel API changes/additions
For Kernel ABI I found a tool for that (and your use case):
https://developers.redhat.com/blog/2018/03/28/analyzing-binary-interface-changes-linux-kernel/

Related

Yocto add driver from newer kernel version

I need to add a wireless driver to a Yocto image that uses kernel 3.10.17. My problem is that the driver entered mainline kernel since version 3.11 (and it is also part of the backports project). I have read the Yocto documentation about kernel development, but it more confused me. What is the proper way to accomplish this? (I suppose adding the driver sources by hand is not).
First: It's not clear which Yocto version you are using. So you might want to update to the current 1.7 version (Dizzy) which provides Kernel 3.10, 3.14 and 3.17.
You can find the kernel configuration in meta/recipes-kernel/linux. Be aware that a BSP or any other layer can also provide other kernel versions/configuration as well as limiting accepted/working version (especially if you use a BSP).
That said, you can define the kernel version that should be used by adding/adjusting PREFERRED_VERSION. An example is PREFERRED_VERSION_linux-stable = "3.10". Another one you can find is PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-dev".
Please be aware that just choosing another kernel doesn't guarantee that the kernel module you want to have will be automatically build. You might need to adjust the kernel configuration to compile it into the kernel or build it as module.

Get kernel version | Linux kernel API [duplicate]

how can I obtain runtime information about which version of kernel is running from inside linux kernel module code (kernel mode)?
By convention, Linux kernel module loading mechanism doesn't allow loading modules that were not compiled against the running kernel, so the "running kernel" you are referring to is most likely is already known at kernel module compilation time.
For retrieving the version string constant, older versions require you to include <linux/version.h>, others <linux/utsrelease.h>, and newer ones <generated/utsrelease.h>. If you really want to get more information at run-time, then utsname() function from linux/utsname.h is the most standard run-time interface.
The implementation of the virtual /proc/version procfs node uses utsname()->release.
If you want to condition the code based on kernel version in compile time, you can use a preprocessor block such as:
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
...
#else
...
#endif
It allows you to compare against major/minor versions.
You can only safely build a module for any one kernel version at a time. This means that asking from a module at runtime is redundant.
You can find this out at build time, by looking at the value of UTS_RELEASE in recent kernels this is in <generated/utsrelease.h> amongst other ways of doing this.
Why can't I build a kernel module for any version?
Because the kernel module API is unstable by design as explained in the kernel tree at: Documentation/stable_api_nonsense.txt. The summary reads:
Executive Summary
-----------------
You think you want a stable kernel interface, but you really do not, and
you don't even know it. What you want is a stable running driver, and
you get that only if your driver is in the main kernel tree. You also
get lots of other good benefits if your driver is in the main kernel
tree, all of which has made Linux into such a strong, stable, and mature
operating system which is the reason you are using it in the first
place.
See also: How to build a Linux kernel module so that it is compatible with all kernel releases?
How to do it at compile time was asked at: Is there a macro definition to check the Linux kernel version?

How to port a linux driver , which is compiled in 2.6 kernel ,without compiling in other new version of kernel

Thanks to every one,
This is the question asked in one of the interview i faced.
I have a Linux device driver which was compiled in Linux kernel version 2.6.I would like to port the same driver in a Linux PC which has kernel 3.X without compiling in new versions.
Is it possible ? If it is possible please let me know how. If it is not possible please let me know why not ?
Thanks & Regards
Siva
No you cannot port module which is compiled for one version to other version.
The reason is as follows
Modules are strongly tied to the data structures and function prototypes defined in a particular kernel version;
the interface seen by a module can change significantly from one kernel version to
the next. This is especially true of development kernels, of course
The kernel does not just assume that a given module has been built against the
proper kernel version. One of the steps in the build process is to link your module
against a file (called vermagic.o) from the current kernel tree; this object contains a
fair amount of information about the kernel the module was built for, including the
target kernel version, compiler version, and the settings of a number of important
configuration variables. When an attempt is made to load a module, this information
can be tested for compatibility with the running kernel. If things don’t match,
the module is not loaded; instead, you see something like:
# insmod hello.ko
Error inserting './hello.ko': -1 Invalid module format
A look in the system log file (/var/log/messages or whatever your system is configured
to use) will reveal the specific problem that caused the module to fail to load.
Kernel interfaces often change between releases. If you are writing a module that is
intended to work with multiple versions of the kernel (especially if it must work
across major releases), you likely have to make use of macros and #ifdef constructs
to make your code build properly.
now it's not possible:
usually, a "driver" is a binary kernel-module
porting will involve code-changes to the kernel module. if you change the code, you need to compile it, in order to get a binary.
since kernel modules run in kernel space, it is crucial that they are robust. since parts of the kernel-API change every now and then, trying to use a module compiled for kernel-X with another kernel-Y, might either not load because of missing symbols (if you are lucky) or lead to a kernel panic because semantics have changed.
btw, all this is not really related to 2.6.x vs 3.y, but holds true for any kernel version
but then: of course in theory it is possible to "write" a kernel-module as binary code in your favourite hex-editor, without resorting to compilers and such. this would allow you to "port" a driver from one kernel to another without recompilation. i guess this is not for humans though...

Upgrade a specific Linux Kernel Subsystem?

Is it possible to upgrade only a specific sub-system, say I2C, of the Linux Kernel.
For example:
Is it possible to include "Support for multiplexed I2C bus topologies (introduced in Kernel 2.6.36)" in the Kernel version 2.6.31.1.
No this is not possible.
A kernel module or 'subsystem' (eg the i2c module) is build for a specific kernel image, you cannot combine different kernel(module) versions.
If you are feeling lucky (depending on your kernel skills), you could:
download the source code of your kernel
Install compiler and friends
add the updated ic2 driver
Try to compile the module for your kernel version
Cross your fingers and load it into your own kernel...\
I do not have any experience with this, so I do not know whether this works or not. Of course, if the ic2 module requires other (updated) modules, you could be ending up with updating (almost) the complete kernel...

glibc: elf file OS ABI invalid

downloaded and compiled glibc-2.13. when i try to run a sample C program which does a malloc(). I get following error
elf file OS ABI invalid
Can anybody please pass my any pointer helpful in resolving this issue.Please note that my kernel version is linux-2.6.35.9
It's not your kernel version that's the problem.
The loader on your system does not support the new Linux ABI. Until relatively recently, Linux ELF binaries used the System V ABI. Recently, in support of STT_GNU_IFUNC, the Linux ABI was added. You would have to update your system C library to have a loader that support STT_GNU_IFUNC, and then it will also recognize ELF objects with the Linux ABI type.
See Dave Miller's blog entry on STT_GNU_IFUNC for Sparc (archived) to gain an understanding of what STT_GNU_IFUNC does, if you care.
If you get your hands in the loader from a newer system, you might be able to make it work using that. But you'll have to carry the loader wherever your program go. You can either compile your program to use that loader as explained here, or compile your program and patch it later using patchelf, in a way similar to what I mention here. I was able to run a program that was giving me the OS ABI invalid error on a linux 2.6.18 (older than yours) that had ld-2.5.so, by copying a ld-2.15.so from somewhere else.
NOTE: do NOT overwrite your system ld*.so or ld-linux. ;-/
It is possible your glibc was built with the --enable-multiarch flag that forced using ifunc and new LINUX ABI
From what I can tell is that --enable-multiarch is the default setting and you should disable it by setting --enable-multiarch=no.

Resources