Compile linux kernel (2.6) module including non kernel headers - linux

Is it possible to compile a linux kernel(2.6) module that includes functionality defined by non-kernel includes?
For example:
kernelmodule.h
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> // printk()
// ...
#include <openssl/sha.h>
// ...
Makefile
obj-m := kernelmodule.o
all:
$(MAKE) -C /lib/modules/`uname -r`/build M=`pwd` modules
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=`pwd` clean
$(RM) Module.markers modules.order
The kernel module I have written and are trying to compile contains functionality found in a number of openssl include files.
The standard makefile presented above doesn't allow includes outside of the linux headers. Is it possible to include this functionality, and if so, could you please point me in the right direction.
Thanks,
Mike

The kernel cannot use userspace code and must stand alone (i.e. be completely self contained, no libraries), therefore it does not pick up standard headers.
It is not clear what benefit trying to pick up userspace headers is. If there are things in there that it would be valid to use (constants, some macros perhaps provided they don't call any userspace functions), then it may be better to duplicate them and include only the kernel-compatible parts that you need.
It is not possible to link the kernel with libraries designed for userspace use - even if they don't make any OS calls - because the linking environment in the kernel cannot pick them up.
Instead, recompile any functions to be used in the kernel (assuming they don't make any OS or library calls - e.g. malloc - in which case they'll need to be modified anyway). Incorporate them into your own library to be used in your kernel modules.
Recent versions of linux contain cryptographic functions anyway, including various SHA hashes - perhaps you can use one of those instead.
Another idea would be to stop trying to do crypto in kernel-space and move the code to userspace. Userspace code is easier to write / debug / maintain etc.

I have taken bits of userspace code that I've written and converted it to work in kernel space (i.e. using kmalloc(), etc), it's not that difficult. However, you are confined to the kernel's understanding of C, not userspace, which differs slightly .. especially with various standard int types.
Just linking against user space DSO's is not possible — the Linux kernel is monolithic, completely self contained. It does not use userspace libc, libraries or other bits as others have noted.
9/10 times, you will find what you need somewhere in the kernel. It's very likely that someone else ran into the same need you have and wrote some static functions in some module to do what you want .. just grab those and re-use them.
In the case of crypto, as others have said, just use what's in the kernel. One thing to note, you'll need them to be enabled in kconfig which may or may not happen depending on what the user selects when building it. So, watch out for dependencies and be explicit, you may have to hack a few entries in kconfig that also select the crypto API you want when your module is selected. Doing that can be a bit of a pain when building out of tree.
So on the one hand we have "just copy and rename stuff while adding overall bloat", on the other you have "tell people they must have the full kernel source". It's one of the quirks that come with a monolithic kernel.
With a Microkernel, almost everything runs in userspace, no worries linking against a DSO for some driver ... it's a non issue. Please don't take that statement as a cue to re-start kernel design philosophy in comments, that's not in the scope of this question.

Related

How to build an external linux module which uses a custom library

I am trying to compile an external linux driver with the the line below within an existing platform using many dependencies (such as libraries):
obj-m += mydriver.o
KDIR ?= $(OUT_DIR)
default:
$(MAKE) -C $(KDIR) M=$$PWD
clean:
$(MAKE) -C $(KDIR) M=$$PWD clean
modules:
$(MAKE) -C $(KDIR) M=$$PWD modules
I have noticed that this invokes the kernel Makefile with creates object files and does the link in order to prepare a "module".ko loadable with linux. But what if, I have to use a specific library (eg. my_library.a): how can I prevent the Linux makefile to take into account this extra library when linking all the object files
Appendice:
My_library.a is a c++ source code contains functions that access to FPGA registers in order to report some useful data. Then my_driver (since it is a C code source , I had to create an C- interface from my_library.a ) will prepare basic system calls accessible from a user-space application. Bottom of line, my_driver reads from FPGA with 8khz, thanks to my_library.a via a C-interface and make data readable for user-space APP.
Cheers,
sahbi
Most probably, you cannot use an application-level external library libmy.a or my_library.a in any kernel module (or kernel code). Such libraries are generally built above the C standard library (e.g. because they use <stdio.h> thru fprintf or <stdlib.h> thru malloc), which does not exist for kernel code.
Conceptually kernel modules and kernel code is freestanding (i.e. not above the C standard library).
Notice that the ABI & calling conventions might be different in kernel code and in application code. And certainly, some standard functions (like malloc, printf, snprintf ....) might not exist inside the kernel. BTW kernel code is not allowed to use floating point, etc...
Of course, you could link your own kernel library (out of your own kernel object files), but that is often not worthwhile.
(an improbable exception could be some external library which do not use any standard C function and do not compute with floating point, but that does not happen in pracice)
At last, the conventional wisdom is to avoid needing lot of kernel code. So you should consider having some helper user-mode process. See netlink(7).
You probably should redesign your driver to avoid needing any external library. Since you read the FPGA at only 8KHz, that part of your code could sit in user-land above existing system calls.
Notice that kernel code cannot be written in C++

How to link kernel functions to user-space program?

I have a user-space program (Capstone). I would like to use it in FreeBSD kernel. I believe most of them have the same function name, semantics and arguments (in FreeBSD, the kernel printf is also named printf). First I built it as libcapstone.a library, and link my program with it. Since the include files are different between Linux user-space and FreeBSD kernel, the library cannot find symbols like sprintf, memset and vsnprintf. How could I make these symbols (from FreeBSD kernel) visible to libcapstone.a?
If directly including header files like <sys/systm.h> in Linux user-space source code, the errors would be like undefined type u_int or u_char, even if I add -D_BSD_SOURCE to CFLAGS.
Additionally, any other better ways to do this?
You also need ; take a look at kernel man pages, eg "man 9 printf". They list required includes at the top.
Note, however, that you're trying to do something really hard. Some basic functions (eg printf) might be there; others differ completely (eg malloc(9)), and most POSIX APIs are simply not there. You won't be able to use open(2), socket(2), or fork(2).

Grub bootloader with shared library support

I'd like to load a shared library (closed-source binary user-space library) at boot stage with grub boot-loader. Are there any chances for this or I must write a custom-elf-loader (grub module) to do it?
29/08/2014: For more detail, this is a programming problem in which I
want to customize or add some new features to Grub boot-loader
project. Thank you for your all supporting!
So, you don't make it crystal clear what you are trying to do, but:
Loading a userspace (assuming Linux SysV ELF type) shared library straight into GRUB is not possible. GRUB modules are indeed in ELF format, but they contain additional headers. Among the information contained in that header is an explicit license statement - GRUB will refuse to load any modules that are not explicitly GPLv2+, GPLv3 or GPLv3+.
It should be possible to write an ELF loader, but an easier way might be to write a tool to convert a userspace library to a GRUB module. There would of course be several restrictions here:
You would need to ensure the userspace library performed no system calls - GRUB would have nothing in place to handle them.
You would need to abide by the licensing rules (so only above three licenses would be acceptable).
You would need to ensure these libraries were not dependent on a global offset table being set up by glibc for them.
If recompiling is an option, GRUB also provides a POSIX emulation layer - add CPPFLAGS_POSIX to your CPPFLAGS, and use core standard POSIX header files. Have a look at the gcrypt support for an example.

Using real time kernel headers to compile userspace code vs default headers

Per customer requirements, I installed CentOS 5.6 with the default kernel. With this kernel installed, the time.h file includes the #define CLOCK_MONOTONIC.
Now, a real-time kernel was installed along with the kernel-devel and our code would like to use CLOCK_MONOTONIC_RAW. It does exist as a part of the kernel's header files, but when I compile our code, it does not find it in the standard userspace includes.
My question is, what is the proper procedure to including/replacing the time.h found by default with the real-time kernel? From my research, it looks like symlinks are bad, so how should it be handled? What is the procedure or process? Upgrading to CentOS 6.0 or 5.7 is not an option per customer requirements. Thanks.
Well, userspace code uses userspace headers. Kernel modules use kernel headers (and that's why symlinks are bad, because you would be mixing userspace code with kernel headers).
To get the definition of CLOCK_MONOTONIC_RAW, you will have to update glibc — for CLOCK_ definitions, the "borderline" (they still count as userspace though!) headers in /usr/include/linux are not used.
With CentOS 5 default install, you are screwed, because both glibc (2.5) and the kernel (2.6.18) are too old; glibc-2.12 (commit glibc-2.12~111) and kernel-2.6.28 are the first to have MONOTONIC_RAW. That means it's got to be CentOS 6, or something else better.
You can try cheating your way in by using something like #ifndef CLOCK_MONOTONIC_RAW, #define CLOCK_MONOTONIC_RAW 4, #endif in your code, but that counts as unportable.
The definition of CLOCK_MONOTONIC_RAW is in /usr/local/include/linux/time.h on our Fedora 11 install but this header appears to be basically unusable . It doesn't declare clock_gettime or define clockid_t but it happily defines struct timerspec and struct itimerspec. The former is preceded by "#ifndef _STRUCT_TIMESPEC" so you can turn it off, but the latter is completely unprotected, which means that you can't include and in the same file without getting conflicting definitions.
There might be some contortion of #include directives that you could use to get this working using the headers in /usr/include, but I gave up and just copied the linux version to the source code directory for my project and then commented out the extra junk that I didn't need. So much for portability.

Disabling vsyscalls in Linux

I'm working on a piece of software that monitors other processes' system calls using ptrace(2). Unfortunately most modern operating system implement some kind of fast user-mode syscalls that are called vsyscalls in Linux.
Is there any way to disable the use of vsyscalls/vDSO for a single process or, if that is not possible, for the whole operating system?
Try echo 0 > /proc/sys/kernel/vsyscall64
If you're trying to ptrace on gettimeofday calls and they aren't showing up, what time source is the system using (pmtimer, acpi, tsc, hpet, etc). I wonder if you'd humor me by trying to force your timer to something older like pmtimer. It's possible one of the many gtod timer specific optimizations is causing your ptrace calls to be avoided, even with vsyscall set to zero.
Is there any way to disable the use of vsyscalls/vDSO for a single process or, if that is not possible, for the whole operating system?
It turns out there IS a way to effectively disable linking vDSO for a single process without disabling it system-wide using ptrace!
All you have to do is to stop the traced process before it returns from execve and remove the AT_SYSINFO_EHDR entry from the auxiliary vector (which comes directly after environment variables along the memory region pointed to in rsp). PTRACE_EVENT_EXEC is a good place to do this.
AT_SYSINFO_EHDR is what the kernel uses to tell the system linker where vDSO is mapped in the process's address space. If this entry is not present, ld seems to act as if the system hasn't mapped a vDSO.
Note that this doesn't somehow unmap the vDSO from your processes memory, it merely ignores it when linking other shared libraries. A malicious program will still be able to interact with it if the author really wanted to.
I know this answer is a bit late, but I hope this information will spare some poor soul a headache
For newer systems echo 0 > /proc/sys/kernel/vsyscall64 might not work. In Ubuntu 16.04 vDSO can be disabled system-wide by adding the kernel parameter vdso=0 in /etc/default/grub under the parameter: GRUB_CMDLINE_LINUX_DEFAULT.
IMPORTANT: Parameter GRUB_CMDLINE_LINUX_DEFAULT might be overwriten by other configuration files in /etc/default/grub.d/..., so double check when to add your custom configuration.
Picking up on Tenders McChiken's approach, I did create a wrapper that disables vDSO for an arbitrary binary, without affecting the rest of the system: https://github.com/danteu/novdso
The general procedure is quite simple:
use ptrace to wait for return from execve(2)
find the address of the auxvector
overwrite the AT_SYSINFO_EHDR entry with AT_IGNORE, telling the application to ignore the following value
I know this is an older question, but nobody has mentioned a third useful way of disabling the vDSO on a per-process basis. You can overwrite the libc functions with your own that performs the actual system call using LD_PRELOAD.
A simple shared library for overriding the gettimeofday and time functions, for example, could look like this:
vdso_override.c:
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/syscall.h>
int gettimeofday(struct timeval *restrict tv, struct timezone *restrict tz)
{
return syscall(__NR_gettimeofday, (long)tv, (long)tz, 0, 0, 0, 0);
}
time_t time(time_t *tloc)
{
return syscall(__NR_time, (long)tloc, 0, 0, 0, 0, 0);
}
This uses the libc wrapper to issue a raw system call (see syscall(2)), so the vDSO is circumvented. You would have to overwrite all system calls that the vDSO exports on your architecture in this way (listed at vdso(7)).
Compile with
gcc -fpic -shared -o vdso_override.so vdso_override.c
Then run any program in which you want to disable VDSO calls as follows:
LD_PRELOAD=./vdso_override.so <some program>
This of course only works if the program you are running is not actively trying to circumvent this. While you can override a symbol using LD_PRELOAD, if the target program really wants to, there is a way to find the original symbol and use that instead.

Resources