How can I Execute/Call a user-space defined function from Linux kernel space module?

gaston

I am developing a Linux module which I want to use to run my C program from kernel mode.

My problem here, in function read() of the module, I need to use a function named eval_keycode(), which is defined in my user space program.

When I try to compile my module, this error occurs :

error: implicit declaration of function ‘eval_keycode’

which is confirming my problem described above.

This is the read() function of my module :

ssize_t exer_read(struct file *pfile, char __user *buffer, size_t length, loff_t *offset) {
    struct file *f = pfile->private_data;
    enum { MAX_BUF_SIZE = 4096 };
    size_t buf_size = 0;
    char *buf = NULL;
    ssize_t total = 0;
    ssize_t rc = 0;

    struct input_event  *ev;
    int yalv;

    /* Allocate temporary buffer. */
    if (length) {
        buf_size = min_t(size_t, MAX_BUF_SIZE, length);
        ev = kmalloc(buf_size, GFP_KERNEL);
        if (ev == NULL) {
            return -ENOMEM;
        }
    }

    /* Read file to buffer in chunks. */
    do {
        size_t amount = min_t(size_t, length, buf_size);

        rc = kernel_read(f, ev, amount, offset);
        if (rc > 0) {
            /* Have read some data from file. */
            if (copy_to_user(buffer, ev, rc) != 0) {
                /* Bad user memory! */
                rc = -EFAULT;
            } else {
                /* Update totals. */
                total += rc;
                buffer += rc;
                *offset += rc;
                length -= rc;

        for (yalv = 0; yalv < (int) (rc / sizeof(struct input_event)); yalv++) {
            if (ev[yalv].type == EV_KEY) {
                if (ev[yalv].value == 0)
                    eval_keycode(ev[yalv].code);
            }
        }


                if (rc < amount) {
                    /* Didn't read the full amount, so terminate early. */
                    rc = 0;
                }
            }
        }
    } 
    while (rc > 0 && length > 0);

    /* Free temporary buffer. */
    kfree(buf);

    if (total > 0) {
       return total;
    }
    return rc;
}

This is my user space eval_keycode() defined function :

void eval_keycode(int code)
{
    static int red_state = 0;
    static int green_state = 0;

    switch (code) {
    case 260:
        printf("BTN left pressed\n");

        /* figure out red state */
        red_state = red_state ? 0 : 1;

        change_led_state(LED_PATH "/" red "/brightness", red_state);
        break;

    case BTN_RIGHT:
        printf("BTN right pressed\n");

        /* figure out green state */
        green_state = green_state ? 0 : 1;

        change_led_state(LED_PATH "/" green "/brightness", green_state);
        break;
    }
}

How can call the eval_keycode function from user space in order to solve this problem ?

Thank you.

mevets

You can, but it is a really bad idea. You need to establish a pointer to your user mode function, arrange for the process containing that function to be running (in the kernel) when you invoke it. That is a lot of work, and is fundamentally malware due to the security holes it creates. Additionally, in the mad dash to lock the door to the now empty barn in the wake of spectre et al, new layers of hackery are being deployed in newer CPUs to make this even harder.

A different approach:

In your original query, you are running this driver as a "tee"; that is, you take the input you receive from the device, give a copy to the caller, and call eval_keycode with each input. Eval_keycode doesn't modify the data, and the kernel module discards it afterwards. So Eval_keycode doesn't really need to be a function; or rather, there could be a user function:

void ProcessEvents(int fd) {
    struct input_event ev;
    while (read(fd, &ev, sizeof ev) == sizeof ev) {
        eval_keycode(&ev);
    }
}

if you could arrange for all the events to be fed into that fd. With this setup, your problem becomes more plumbing than kernel renovation. The user creates a pipe/socket/fifo/... and passes the write end to your kernel module (yay more ioctl()s). Your kernel module can then carefully use kernel_write() ( or vfs_write if you are stuck in the past ) to make these events available to the user handler. It wants to be careful about where its blocking points are.

You could extend this to work as a transform; that is where your driver transforms the events via a user mode handler; but at that point, you might really consider FUSE a better solution.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to call a self-defined Kernel function in the user space?

Calling a user defined function in kernel space from user space application program

How to communicate with a Linux kernel module from user space without littering /dev with new nodes?

Can I pass a pointer to linux kernel space for a __user parameter?

How to make communication between user space program and Linux kernel module in order to print a message sent from user program to the kernel

How can i pass the address of a buffer in user space to kernel

copy data from linux kernel space to user space

How to mmap a Linux kernel buffer to user space?

How to send signal from Linux kernel space to user space in order to notify about an input hardware event

How to access(if possible) kernel space from user space?

How to correctly extract a string from a user space pointer in kernel space?

Linux kernel module communicate with user space through UNIX socket

Unable to print the message sent from user space C application to linux kernel module

Can kernel module take initiative to send message to user space with netlink?

copy data from kernel space to user space

How can I get the CPU core number from within a user-space app (Linux, C)?

map a buffer from Kernel to User space allocated by another module

How do you register a region of user space memory in a kernel module?

Can I replace a Linux kernel function with a module?

How can I clone a module from linux kernel?

How to add a custom Extended Attribute from Linux kernel space (i.e from a custom system call)

user space library in Linux kernel modal - for testing

Has Linux always separated User and Kernel space?

How to access the node created in user space from kernel?

Memory-Debuging: How to get locked pages information in user space/kernel space in linux

Understanding the Loading of Modules by initramfs in Linux: User Space or Kernel Space

How can I set rtc time in kernel space?

Kernel OOPs causes when accessing user space pointer from within the Linux Kernel

uevent sent from kernel to user space (udev)