any example of copy_from_user() ? kernel and userspace
Look into code you have given, it seems that you want to handle SIGIO
signal
Here is my attempt to solve your problem,
signal_kernel.c
file :
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/siginfo.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/signal.h>
#include <linux/debugfs.h>
#include <linux/pid.h>
#define MAX 10
MODULE_LICENSE("GPL");
struct dentry *file;
static ssize_t write_conf_pid(struct file *file, const char *buf,
size_t count, loff_t *position)
{
char temp_str[MAX];
int ret;
int pid = 0;
struct siginfo sinfo;
struct task_struct *task;
/* NEVER TRUST USER INPUT */
if (count > MAX)
return -EINVAL;
if (copy_from_user(temp_str, buf, MAX) != 0)
return -EFAULT;
ret = sscanf(temp_str, "%d", &pid);
if (ret != 1) {
pr_info("Error in reading PID value from user");
return -EINVAL;
}
pr_info("User entered pid %d\n", pid);
memset(&sinfo, 0, sizeof(struct siginfo));
sinfo.si_signo = SIGIO;
sinfo.si_code = SI_USER;
task = pid_task(find_vpid(pid), PIDTYPE_PID);
if (task == NULL) {
pr_info("Cannot find PID from user program\r\n");
return -ENODEV;
}
ret = send_sig_info(SIGIO, &sinfo, task);
if (ret < 0)
pr_info("Error sending signal\n");
return count;
}
static const struct file_operations my_fops = {
.write = write_conf_pid,
};
int init_module()
{
/* Only root can write to this file */
file = debugfs_create_file("pidconf", 0200, NULL, NULL, &my_fops);
return 0;
}
void cleanup_module()
{
pr_info("\nGoodBye World\n\n");
}
signal_user.c
file :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
void signal_handler(int signum)
{
if (signum == SIGIO)
printf("SIGIO\r\n");
return;
}
int main()
{
int i = 1;
signal(SIGIO, signal_handler);
printf("My PID is %d.\n", getpid());
while (i);
return 0;
}
After compiling and running both user space and kernel space program, use debugfs
interface to send PID value to Kernel space,
$ insmod signal_kernel.ko
$ ./signal_user
My PID is 17633.
... # Process will run in loop due to while(1)
From another terminal, provide PID to debugfs
interface,
$ echo 17633 > /sys/kernel/debug/pidconf
There are various ways (sysfs
, misc_char_device
, char device
etc.) to this task, but this will give you brief idea about using copy_from_user()
and copy_to_user()
Please note that there is little error handling done in signal_user.c
and signal_kernel.c
.
Raheel
Updated on June 04, 2022Comments
-
Raheel almost 2 years
I am looking for copying PID value from User space to Kernel space, here is my code snaps.
Kernel Module:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/siginfo.h> #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/uaccess.h> #include <linux/signal.h> MODULE_LICENSE ("GPL"); struct siginfo sinfo; pid_t pid; struct task_struct *task; int init_module() { memset(&sinfo, 0, sizeof(struct siginfo)); sinfo.si_signo = SIGIO; sinfo.si_code = SI_USER; pid = 5218; // Everytime a new PID // task = find_task_by_vpid(pid); I am also working on new and old version of UBUNTU so thats why this is here task = pid_task(find_vpid(pid), PIDTYPE_PID); printk("%d .\n", task); if(task == NULL) { printk("Cannot find PID from user program\r\n"); return 0; } send_sig_info(SIGIO, &sinfo, task); return 0; } void cleanup_module () { printk(KERN_ALERT"\nGoodBye World\n\n"); }
Userspace Code:
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> void signal_handler(int signum) { if (signum == SIGIO) printf("SIGIO\r\n"); return; } int main() { int i = 1; signal(SIGIO, signal_handler); printf("My PID is %d.\n", getpid()); while (i); return 0; }
Now, here I am always running user space program to get PID and then I always have to edit the pid variable in Kernel module.
I found one way to access information from user space into Kernel space and vice-versa (i.e., using
copy_from/to_user()
)But I am unable to understand either of them for getting a PID from user space, I have to make file in
/dev
directory and should apply all the required functions for just getting PID?Is there any other way? if not, then can anyone please help me to do this? I am new in c programming and playing with kernel module directly so its hard for me.