Reputation: 331
I have successfully implemented a custom syscall getpuid()
, and now I need to write a custom dynamically loadable module to export a function which has exactly the same functionality of the custom system call getpeuid()
. This syscall is used to get the euid of the calling process's parent process. And the segment of the custom module:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/printk.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/cred.h>
static int *getpeuid(pid_t pid, uid_t *uid)
{
// Code to get the parent process euid
......;
}
EXPORT_SYMBOL(getpeuid);
/* This function is called when the module is loaded. */
int getpeuid_init(void)
{
printk(KERN_INFO "getpeuid() loaded\n");
return 0;
}
/* This function is called when the module is removed. */
void getpeuid_exit(void) {
printk(KERN_INFO "Removing getpeuid()\n");
}
/* Macros for registering module entry and exit points. */
module_init( getpeuid_init );
module_exit( getpeuid_exit );
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Return parent euid.");
MODULE_AUTHOR("CGG");
I have successfully compiled this custom module and insert module into the kernel. Then, I wrote a test to test the functionality of the function exported from the loadable kernel module implemented:
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid;
uid_t *uid;
uid = (uid_t *)malloc(sizeof(uid_t));
pid = getppid();
int retval = getpeuid(pid, uid);
if( retval < 0 )
{
perror("My system call returned with an error code.");
}
printf("My syscall's parameters: %ld \n", pid);
printf("My system call returned %d.\n", retval);
printf("Current values: uid=%ld \n", *uid);
return 0;
}
But when I am compiling the test script, it gives me the following error:
/tmp/ccV8WTx0.o: In function 'main': hw5-test.c:(.text+0x33): undefined reference to `supermom' collect2: error: ld returned 1 exit status
I checked the available symbols in the system using cat /proc/kallsyms
, and the symbol I exported is there:
fa0eb000 T getpeuid [getpeuid]
I just don't know how am I supposed to use my custom function then, since I don't have a header file for my custom module to be included in my test script. Even if I need to write a header file, I don't know how to write a header file for custom kernel module.
Could someone give me a hand here?
Thanks in advance!
EDIT:
I am only allowed to use the dynamically loadable kernel module to simulate the functionality of the syscall.
EDIT:
I am not allowed to modify the system call table in the module initialization code.
I got the following link from others as a hint:
Upvotes: 1
Views: 2573
Reputation: 22487
Checkout the list of various Linux kernel <--> Userspace interfaces.
To allow userspace to interact with a loadable kernel module, consider using sysfs.
To add support for sysfs within your loadable module, checkout the basics of a sys-fs entry.
A good guide with the best practices of creating sysfs entries should get you started the right way.
The userspace test will then change from
int retval = getpeuid(pid, uid);
to something that uses open
, write()
and read()
to interact with the sysfs entry just like a regular file.
( Why file? because everything is a file on UNIX. )
You could further simplify this to using a shell-script that uses echo
/cat
commands to pass/gather data from the loadable kernel module via the sysfs entry.
Disclaimer: I agree that trying to use syscalls within a loadable kernel module is neither a proper solution, nor guaranteed to always work. I know what i am doing.
(Hover the mouse over the following block, ONLY if you agree to the above)
Checkout this answer and related code that describes a potential "hack" to allow implementing custom syscalls in loadable modules in any unused locations within the current syscall table of the kernel.
Also carefully go through the several answers/comments to this question. They deal with overcoming the problem of not being able to modify the syscall table. One of the comments also emphasises the fact that hypervisors implementing their own extensions are not likely to be affected by this "exploit" as they offer better protection of the syscall table.
Note that such non-standard interfaces may not always work and even if they do, they can stop working anytime. Stick to standard interfaces for reliability.
Upvotes: 3
Reputation: 34537
EXPORT_SYMBOL exports the symbol within the kernel, so that other kernel modules can use it. It will not make it available to userland programs. Adding a new system call doesn't appear to be possible via a kernel module: https://unix.stackexchange.com/questions/47701/adding-a-new-system-call-to-linux-3-2-x-with-a-loadable-kernel-module
Upvotes: 1