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.
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.
Comments