public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Implement uhook(call kernel func from userspace) driver
       [not found] <CAN_1RdvqJRig8vZW_gcvNVKYNo7ROmEKxAs7qu1N6XE4+Pspjg@mail.gmail.com>
@ 2012-06-23  3:24 ` Peiyong Feng
  2012-06-23  3:41 ` Peiyong Feng
       [not found] ` <20120623040633.GA16278@kroah.com>
  2 siblings, 0 replies; 8+ messages in thread
From: Peiyong Feng @ 2012-06-23  3:24 UTC (permalink / raw)
  To: linux-kernel

Hi all,

This patch implement the uhook kernel driver. Here are some ideals and
explanations:

1. What is uhook

uhook(userspace kernel hook) means call kernel function from
userspace. That is to say, we can

write a function in kernel space and call it in userspace while the
kernel Image is running. For example:


I write  a function in kernel, like following:

+int uhook_unlock(void)
+{
+       printk(KERN_INFO"Unlock mutex\n");
+       mutex_unlock(&uhook_global->mutex);
+       return -1;
+}
+EXPORT_SYMBOL_GPL(uhook_test);

I can call it from userspace using uhook application:

uhook --type run uhook_test


2. What we can do with uhook

The most exciting feature of uhook is that we call kernel function in
userspace while kernel is running.
So,

A. We can using uhook to dump value of kernel argument when some thing
goes wrong. Especially when
the device driver cannot work correctly, we can dump some device
registers to examine what is going on.

B. We can implement some switch in kernel to control if branch. For example:

if (branch_control) {
     balabalabala......
     .....
}

We can dynamic change the value of branch_control to let kernel run
the specific code or not.

C. Whatever you want kernel do.



3. Compare to /proc or /sys file system

Kernel has some component like /proc and /sys file system to perform
the communication between kernel
and user space. But they are so complex that we must write some code
very time we want to use them. However,
with uhook, we just need to insmod the uhook.ko, then call the kernel
function whenever and wherever.


4. TODO

A. This version of uhook, can just support kernel function prototype
like int func(void). I donot know how to deal
with the function that has many argument and variable return type.

B. The user space applicantion: uhook, is just a test, so poor, cannot
process complex command option, I am still
working on it



-----------------------------------------------------------------------------------------------------------------------------------


>From 0aeb2765532829f0b5cfdde57de964f1620bb5ca Mon Sep 17 00:00:00 2001
From: bigfeng12 <peiyong.feng.kernel@gmail.com>
Date: Sat, 23 Jun 2012 10:31:20 +0800
Subject: [PATCH] Implement uhook(call kernel func from userspace) driver

Signed-off-by: bigfeng12 <peiyong.feng.kernel@gmail.com>
---
 drivers/staging/uhook/Kconfig  |    3 +
 drivers/staging/uhook/Makefile |    1 +
 drivers/staging/uhook/uhook.c  |  307 ++++++++++++++++++++++++++++++++++++++++
 tools/uhook/Makefile           |    2 +
 tools/uhook/uuhook.c           |   89 ++++++++++++
 5 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/uhook/Kconfig
 create mode 100644 drivers/staging/uhook/Makefile
 create mode 100644 drivers/staging/uhook/uhook.c
 create mode 100644 tools/uhook/Makefile
 create mode 100644 tools/uhook/uuhook.c

diff --git a/drivers/staging/uhook/Kconfig b/drivers/staging/uhook/Kconfig
new file mode 100644
index 0000000..074aeb8
--- /dev/null
+++ b/drivers/staging/uhook/Kconfig
@@ -0,0 +1,3 @@
+config UHOOK
+       tristate "Call kernel func from user space(uhook) driver"
+       default n
diff --git a/drivers/staging/uhook/Makefile b/drivers/staging/uhook/Makefile
new file mode 100644
index 0000000..d0d7d74
--- /dev/null
+++ b/drivers/staging/uhook/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_UHOOK)    += uhook.o
diff --git a/drivers/staging/uhook/uhook.c b/drivers/staging/uhook/uhook.c
new file mode 100644
index 0000000..3f77443
--- /dev/null
+++ b/drivers/staging/uhook/uhook.c
@@ -0,0 +1,307 @@
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
+#include <linux/kallsyms.h>
+
+#include <asm/ioctls.h>
+
+/*struct uhook*/
+#define   MAX_ARGV_LEN  512                    /*The length of the
buffer used to staorge argv*/
+#define   UHOOK_STA_LEN         32                     /*The length
of the buffer used to staorge argv*/
+
+
+#define   UHOOKCMD_QUERY_FUNC  1               /*CMD used to query if
there is a
symbal in kernel*/
+#define   UHOOKCMD_QUERY_VAL   2               /*CMD used to query
the value of a
argument in kernel*/
+#define   UHOOKCMD_RUN         3               /*CMD used to run the
func in kernel*/
+
+
+
+struct uhook{
+       char            fun_name[KSYM_NAME_LEN];/*function name called
from userspace*/
+       char            argv[MAX_ARGV_LEN];     /*argv of function*/
+       int             argc;                   /*number of arg*/
+       int             ret;                    /*return value*/
+       char            status[UHOOK_STA_LEN];  /*status of kernel func run*/
+       unsigned long   addr;                   /*Address of the kernel symbal*/
+};
+
+struct uhook_desc{
+       struct miscdevice       misc;           /*The misc device*/
+       struct mutex            mutex;          /*mutex used to protect*/
+};
+
+static struct uhook_desc *uhook_global;
+
+int uhook_unlock(void)
+{
+       printk(KERN_INFO"Unlock mutex\n");
+       mutex_unlock(&uhook_global->mutex);
+       return -1;
+}
+
+int  uhook_test(void)
+{
+       printk(">>>>>>>>>>uhook test sucessfully<<<<<<<<<<<<<<<<<<<\n");
+       return -1;
+}
+EXPORT_SYMBOL_GPL(uhook_test);
+EXPORT_SYMBOL_GPL(uhook_unlock);
+
+
+static ssize_t uhook_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *pos)
+{
+       return 0;
+}
+
+
+
+static ssize_t uhook_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                        unsigned long nr_segs, loff_t ppos)
+{
+       return 0;
+}
+
+
+
+static int uhook_open(struct inode *inode, struct file *file)
+{
+
+       file->private_data = uhook_global;
+       printk(KERN_INFO"Open uhook device success\n");
+       return 0;
+}
+
+static int uhook_release(struct inode *ignored, struct file *file)
+{
+       return 0;
+}
+
+
+static long uhook_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct uhook_desc *desc = file->private_data;
+       struct uhook *tmp = (struct uhook *)arg;
+
+       /*Status of kernel function run*/
+       char *exsit = "exsit";
+       char *noexsit = "no-exsit";
+       char *success = "success";
+       char *fail = "fail";
+
+       struct uhook    uhook;
+       unsigned long addr;
+       int ret = 0;
+       int val = 0;
+
+       memset(&uhook, 0, sizeof(struct uhook));
+       mutex_lock(&desc->mutex);
+
+       switch (cmd) {
+       case UHOOKCMD_QUERY_FUNC:
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       ret = 0;
+                       if (copy_to_user(&tmp->ret, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, exsit, strlen(exsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+
+               } else {
+                       ret = -1;
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, noexsit,
strlen(noexsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       case UHOOKCMD_QUERY_VAL:
+       /*TODO:
+        * this version of uhook can just return the int value(4 byte for 32
bit system)
+        * from kernel space to user space. And if the value is -1,
how to deal it?*/
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       val = *(int *)addr;
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &val, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, success,
strlen(success))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               } else {
+                       ret = -1;
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, fail, strlen(fail))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       case UHOOKCMD_RUN:
+       /*This is the point. Call kernel space function from user space
+        * TODO:
+        * This version of uhook can just support function type like:
+        * int func(void)*/
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       int (*func)(void);
+                       func = (int (*)(void))addr;
+                       ret = func();
+
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, success,
strlen(success))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               } else {
+                       ret = -1;
+
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, noexsit,
strlen(noexsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       default:
+               printk(KERN_ERR"Unknown cmd\n");
+       }
+
+       mutex_unlock(&desc->mutex);
+
+       return ret;
+}
+
+static const struct file_operations uhook_fops = {
+       .owner = THIS_MODULE,
+       .read = uhook_read,
+       .aio_write = uhook_aio_write,
+       .unlocked_ioctl = uhook_ioctl,
+       .compat_ioctl = uhook_ioctl,
+       .open = uhook_open,
+       .release = uhook_release,
+};
+
+static int __init uhook_init(char *uhook_name)
+{
+       uhook_global = kzalloc(sizeof(struct uhook_desc), GFP_KERNEL);
+       int ret = 0;
+       if (!uhook_global)
+               return -ENOMEM;
+
+       /*Do some initilization*/
+       mutex_init(&uhook_global->mutex);
+
+       uhook_global->misc.minor = MISC_DYNAMIC_MINOR;
+       uhook_global->misc.name = kstrdup(uhook_name, GFP_KERNEL);
+       if (uhook_global->misc.name == NULL) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+
+       uhook_global->misc.fops = &uhook_fops;
+       uhook_global->misc.parent = NULL;
+
+       /*Register the misc device for uhook */
+       ret = misc_register(&uhook_global->misc);
+       if (unlikely(ret)) {
+               printk(KERN_ERR "uhook: failed to register misc "
+                      "device for log '%s'!\n", uhook_global->misc.name);
+               goto out_free;
+       }
+
+       printk(KERN_INFO "uhook: created:'%s'\n",
+              uhook_global->misc.name);
+
+       return 0;
+
+out_free:
+       kfree(uhook_global);
+
+       return ret;
+}
+static int __init uhook_dev_init(void)
+{
+       if (uhook_init("uhook")) {
+               printk(KERN_ERR"uhook init failed\n");
+               return -1;
+       }
+       printk(KERN_INFO"uhook init success\n");
+       return 0;
+}
+
+static void __exit uhook_dev_deinit(void)
+{
+       misc_deregister(&uhook_global->misc);
+       kfree(uhook_global);
+}
+MODULE_LICENSE("GPL");
+module_init(uhook_dev_init);
+module_exit(uhook_dev_deinit);
diff --git a/tools/uhook/Makefile b/tools/uhook/Makefile
new file mode 100644
index 0000000..4862fc0
--- /dev/null
+++ b/tools/uhook/Makefile
@@ -0,0 +1,2 @@
+all:
+       gcc uuhook.c -o uhook
diff --git a/tools/uhook/uuhook.c b/tools/uhook/uuhook.c
new file mode 100644
index 0000000..87d088d
--- /dev/null
+++ b/tools/uhook/uuhook.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/*struct uhook*/
+#define   MAX_ARGV_LEN  512                    /*The length of the
buffer used to staorge argv*/
+#define   UHOOK_STA_LEN         32                     /*The length
of the buffer used to staorge argv*/
+#define   KSYM_NAME_LEN  128
+struct uhook{
+       char            fun_name[KSYM_NAME_LEN];/*function name called
from userspace*/
+       char            argv[MAX_ARGV_LEN];     /*argv of function*/
+       int             argc;                   /*number of arg*/
+       int             ret;                    /*return value*/
+       char            status[UHOOK_STA_LEN];  /*status of kernel func run*/
+       unsigned long   addr;                   /*Address of kernel symbal*/
+};
+
+
+#define   UHOOKCMD_QUERY_FUNC  1               /*CMD used to query if
there is a
symbal in kernel*/
+#define   UHOOKCMD_QUERY_VAL   2               /*CMD used to query
the value of a
argument in kernel*/
+#define   UHOOKCMD_RUN         3               /*CMD used to run the
func in kernel*/
+
+#define          DEV_NAME              "/dev/uhook"
+
+static int parse_cmd(char *cmd)
+{
+       if (strcmp(cmd, "query") == 0) {
+               return UHOOKCMD_QUERY_FUNC;
+       }
+       if (strcmp(cmd, "run") == 0) {
+               return UHOOKCMD_RUN;
+       }
+       if (strcmp(cmd, "query_val") == 0) {
+               return UHOOKCMD_QUERY_VAL;
+       }
+}
+
+static int parse_result(struct uhook *uhook, char *cmd)
+{
+       printf("The ret of cmd(%s) is %d\n", cmd, uhook->ret);
+       printf("The address of ksymbal(%s) is 0x%x\n",
uhook->fun_name, uhook->addr);
+       printf("The status of ksymbal(%s) run is %s\n", uhook->fun_name,
uhook->status);
+}
+
+static void build_uhook(struct uhook *uhook, char *name)
+{
+       strcpy(uhook->fun_name, name);
+}
+/*
+ * call type:
+ * uhook    --type     run             func
+ * argv[0] argv[1]     argv[2]         argv[3]
+ * */
+int main(int argc, char **argv)
+{
+
+       int uhook_fd = open(DEV_NAME, O_RDWR);
+       struct uhook    uhook;
+       memset(&uhook, 0, sizeof(struct uhook));
+
+       switch(parse_cmd(argv[2])) {
+
+       case UHOOKCMD_QUERY_FUNC:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_QUERY_FUNC, &uhook);
+               parse_result(&uhook, "query");
+               break;
+       case UHOOKCMD_RUN:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_RUN, &uhook);
+               parse_result(&uhook, "run");
+               break;
+       case UHOOKCMD_QUERY_VAL:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_QUERY_VAL, &uhook);
+               parse_result(&uhook, "query val");
+               break;
+       default:
+               printf("Unkown cmd\n");
+       }
+       close(uhook_fd);
+       return 0;
+}
+
--
1.7.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH] Implement uhook(call kernel func from userspace) driver
       [not found] <CAN_1RdvqJRig8vZW_gcvNVKYNo7ROmEKxAs7qu1N6XE4+Pspjg@mail.gmail.com>
  2012-06-23  3:24 ` [PATCH] Implement uhook(call kernel func from userspace) driver Peiyong Feng
@ 2012-06-23  3:41 ` Peiyong Feng
       [not found] ` <20120623040633.GA16278@kroah.com>
  2 siblings, 0 replies; 8+ messages in thread
From: Peiyong Feng @ 2012-06-23  3:41 UTC (permalink / raw)
  To: linux-kernel

Hi all,

This patch implement the uhook kernel driver. Here are some ideals and
explanations:

1. What is uhook

uhook(userspace kernel hook) means call kernel function from
userspace. That is to say, we can

write a function in kernel space and call it in userspace while the
kernel Image is running. For example:


I write  a function in kernel, like following:

+int uhook_unlock(void)
+{
+       printk(KERN_INFO"Unlock mutex\n");
+       mutex_unlock(&uhook_global->mutex);
+       return -1;
+}
+EXPORT_SYMBOL_GPL(uhook_test);

I can call it from userspace using uhook application:

uhook --type run uhook_test


2. What we can do with uhook

The most exciting feature of uhook is that we call kernel function in
userspace while kernel is running.
So,

A. We can using uhook to dump value of kernel argument when some thing
goes wrong. Especially when
the device driver cannot work correctly, we can dump some device
registers to examine what is going on.

B. We can implement some switch in kernel to control if branch. For example:

if (branch_control) {
     balabalabala......
     .....
}

We can dynamic change the value of branch_control to let kernel run
the specific code or not.

C. Whatever you want kernel do.



3. Compare to /proc or /sys file system

Kernel has some component like /proc and /sys file system to perform
the communication between kernel
and user space. But they are so complex that we must write some code
very time we want to use them. However,
with uhook, we just need to insmod the uhook.ko, then call the kernel
function whenever and wherever.


4. TODO

A. This version of uhook, can just support kernel function prototype
like int func(void). I donot know how to deal
with the function that has many argument and variable return type.

B. The user space applicantion: uhook, is just a test, so poor, cannot
process complex command option, I am still
working on it



-----------------------------------------------------------------------------------------------------------------------------------


>From 0aeb2765532829f0b5cfdde57de964f1620bb5ca Mon Sep 17 00:00:00 2001
From: bigfeng12 <peiyong.feng.kernel@gmail.com>
Date: Sat, 23 Jun 2012 10:31:20 +0800
Subject: [PATCH] Implement uhook(call kernel func from userspace) driver

Signed-off-by: bigfeng12 <peiyong.feng.kernel@gmail.com>
---
 drivers/staging/uhook/Kconfig  |    3 +
 drivers/staging/uhook/Makefile |    1 +
 drivers/staging/uhook/uhook.c  |  307 ++++++++++++++++++++++++++++++++++++++++
 tools/uhook/Makefile           |    2 +
 tools/uhook/uuhook.c           |   89 ++++++++++++
 5 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/uhook/Kconfig
 create mode 100644 drivers/staging/uhook/Makefile
 create mode 100644 drivers/staging/uhook/uhook.c
 create mode 100644 tools/uhook/Makefile
 create mode 100644 tools/uhook/uuhook.c

diff --git a/drivers/staging/uhook/Kconfig b/drivers/staging/uhook/Kconfig
new file mode 100644
index 0000000..074aeb8
--- /dev/null
+++ b/drivers/staging/uhook/Kconfig
@@ -0,0 +1,3 @@
+config UHOOK
+       tristate "Call kernel func from user space(uhook) driver"
+       default n
diff --git a/drivers/staging/uhook/Makefile b/drivers/staging/uhook/Makefile
new file mode 100644
index 0000000..d0d7d74
--- /dev/null
+++ b/drivers/staging/uhook/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_UHOOK)    += uhook.o
diff --git a/drivers/staging/uhook/uhook.c b/drivers/staging/uhook/uhook.c
new file mode 100644
index 0000000..3f77443
--- /dev/null
+++ b/drivers/staging/uhook/uhook.c
@@ -0,0 +1,307 @@
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/vmalloc.h>
+#include <linux/kallsyms.h>
+
+#include <asm/ioctls.h>
+
+/*struct uhook*/
+#define   MAX_ARGV_LEN  512                    /*The length of the
buffer used to staorge argv*/
+#define   UHOOK_STA_LEN         32                     /*The length
of the buffer used to staorge argv*/
+
+
+#define   UHOOKCMD_QUERY_FUNC  1               /*CMD used to query if
there is a
symbal in kernel*/
+#define   UHOOKCMD_QUERY_VAL   2               /*CMD used to query
the value of a
argument in kernel*/
+#define   UHOOKCMD_RUN         3               /*CMD used to run the
func in kernel*/
+
+
+
+struct uhook{
+       char            fun_name[KSYM_NAME_LEN];/*function name called
from userspace*/
+       char            argv[MAX_ARGV_LEN];     /*argv of function*/
+       int             argc;                   /*number of arg*/
+       int             ret;                    /*return value*/
+       char            status[UHOOK_STA_LEN];  /*status of kernel func run*/
+       unsigned long   addr;                   /*Address of the kernel symbal*/
+};
+
+struct uhook_desc{
+       struct miscdevice       misc;           /*The misc device*/
+       struct mutex            mutex;          /*mutex used to protect*/
+};
+
+static struct uhook_desc *uhook_global;
+
+int uhook_unlock(void)
+{
+       printk(KERN_INFO"Unlock mutex\n");
+       mutex_unlock(&uhook_global->mutex);
+       return -1;
+}
+
+int  uhook_test(void)
+{
+       printk(">>>>>>>>>>uhook test sucessfully<<<<<<<<<<<<<<<<<<<\n");
+       return -1;
+}
+EXPORT_SYMBOL_GPL(uhook_test);
+EXPORT_SYMBOL_GPL(uhook_unlock);
+
+
+static ssize_t uhook_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *pos)
+{
+       return 0;
+}
+
+
+
+static ssize_t uhook_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                        unsigned long nr_segs, loff_t ppos)
+{
+       return 0;
+}
+
+
+
+static int uhook_open(struct inode *inode, struct file *file)
+{
+
+       file->private_data = uhook_global;
+       printk(KERN_INFO"Open uhook device success\n");
+       return 0;
+}
+
+static int uhook_release(struct inode *ignored, struct file *file)
+{
+       return 0;
+}
+
+
+static long uhook_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct uhook_desc *desc = file->private_data;
+       struct uhook *tmp = (struct uhook *)arg;
+
+       /*Status of kernel function run*/
+       char *exsit = "exsit";
+       char *noexsit = "no-exsit";
+       char *success = "success";
+       char *fail = "fail";
+
+       struct uhook    uhook;
+       unsigned long addr;
+       int ret = 0;
+       int val = 0;
+
+       memset(&uhook, 0, sizeof(struct uhook));
+       mutex_lock(&desc->mutex);
+
+       switch (cmd) {
+       case UHOOKCMD_QUERY_FUNC:
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       ret = 0;
+                       if (copy_to_user(&tmp->ret, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, exsit, strlen(exsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+
+               } else {
+                       ret = -1;
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, noexsit,
strlen(noexsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       case UHOOKCMD_QUERY_VAL:
+       /*TODO:
+        * this version of uhook can just return the int value(4 byte for 32
bit system)
+        * from kernel space to user space. And if the value is -1,
how to deal it?*/
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       val = *(int *)addr;
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &val, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, success,
strlen(success))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               } else {
+                       ret = -1;
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, fail, strlen(fail))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       case UHOOKCMD_RUN:
+       /*This is the point. Call kernel space function from user space
+        * TODO:
+        * This version of uhook can just support function type like:
+        * int func(void)*/
+               if (copy_from_user(&uhook, (struct uhook __user *)arg,
sizeof(struct uhook))) {
+                       mutex_unlock(&desc->mutex);
+                       return -EFAULT;
+               }
+               addr = kallsyms_lookup_name(uhook.fun_name);
+               if (addr) {
+                       int (*func)(void);
+                       func = (int (*)(void))addr;
+                       ret = func();
+
+                       if (copy_to_user(&tmp->addr, &addr,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, success,
strlen(success))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               } else {
+                       ret = -1;
+
+                       if (copy_to_user(&tmp->addr, &ret,
sizeof(unsigned long))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(&tmp->ret, &ret, sizeof(int))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       if (copy_to_user(tmp->status, noexsit,
strlen(noexsit))) {
+                               mutex_unlock(&desc->mutex);
+                               return -EFAULT;
+                       }
+                       mutex_unlock(&desc->mutex);
+               }
+               break;
+       default:
+               printk(KERN_ERR"Unknown cmd\n");
+       }
+
+       mutex_unlock(&desc->mutex);
+
+       return ret;
+}
+
+static const struct file_operations uhook_fops = {
+       .owner = THIS_MODULE,
+       .read = uhook_read,
+       .aio_write = uhook_aio_write,
+       .unlocked_ioctl = uhook_ioctl,
+       .compat_ioctl = uhook_ioctl,
+       .open = uhook_open,
+       .release = uhook_release,
+};
+
+static int __init uhook_init(char *uhook_name)
+{
+       uhook_global = kzalloc(sizeof(struct uhook_desc), GFP_KERNEL);
+       int ret = 0;
+       if (!uhook_global)
+               return -ENOMEM;
+
+       /*Do some initilization*/
+       mutex_init(&uhook_global->mutex);
+
+       uhook_global->misc.minor = MISC_DYNAMIC_MINOR;
+       uhook_global->misc.name = kstrdup(uhook_name, GFP_KERNEL);
+       if (uhook_global->misc.name == NULL) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+
+       uhook_global->misc.fops = &uhook_fops;
+       uhook_global->misc.parent = NULL;
+
+       /*Register the misc device for uhook */
+       ret = misc_register(&uhook_global->misc);
+       if (unlikely(ret)) {
+               printk(KERN_ERR "uhook: failed to register misc "
+                      "device for log '%s'!\n", uhook_global->misc.name);
+               goto out_free;
+       }
+
+       printk(KERN_INFO "uhook: created:'%s'\n",
+              uhook_global->misc.name);
+
+       return 0;
+
+out_free:
+       kfree(uhook_global);
+
+       return ret;
+}
+static int __init uhook_dev_init(void)
+{
+       if (uhook_init("uhook")) {
+               printk(KERN_ERR"uhook init failed\n");
+               return -1;
+       }
+       printk(KERN_INFO"uhook init success\n");
+       return 0;
+}
+
+static void __exit uhook_dev_deinit(void)
+{
+       misc_deregister(&uhook_global->misc);
+       kfree(uhook_global);
+}
+MODULE_LICENSE("GPL");
+module_init(uhook_dev_init);
+module_exit(uhook_dev_deinit);
diff --git a/tools/uhook/Makefile b/tools/uhook/Makefile
new file mode 100644
index 0000000..4862fc0
--- /dev/null
+++ b/tools/uhook/Makefile
@@ -0,0 +1,2 @@
+all:
+       gcc uuhook.c -o uhook
diff --git a/tools/uhook/uuhook.c b/tools/uhook/uuhook.c
new file mode 100644
index 0000000..87d088d
--- /dev/null
+++ b/tools/uhook/uuhook.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/*struct uhook*/
+#define   MAX_ARGV_LEN  512                    /*The length of the
buffer used to staorge argv*/
+#define   UHOOK_STA_LEN         32                     /*The length
of the buffer used to staorge argv*/
+#define   KSYM_NAME_LEN  128
+struct uhook{
+       char            fun_name[KSYM_NAME_LEN];/*function name called
from userspace*/
+       char            argv[MAX_ARGV_LEN];     /*argv of function*/
+       int             argc;                   /*number of arg*/
+       int             ret;                    /*return value*/
+       char            status[UHOOK_STA_LEN];  /*status of kernel func run*/
+       unsigned long   addr;                   /*Address of kernel symbal*/
+};
+
+
+#define   UHOOKCMD_QUERY_FUNC  1               /*CMD used to query if
there is a
symbal in kernel*/
+#define   UHOOKCMD_QUERY_VAL   2               /*CMD used to query
the value of a
argument in kernel*/
+#define   UHOOKCMD_RUN         3               /*CMD used to run the
func in kernel*/
+
+#define          DEV_NAME              "/dev/uhook"
+
+static int parse_cmd(char *cmd)
+{
+       if (strcmp(cmd, "query") == 0) {
+               return UHOOKCMD_QUERY_FUNC;
+       }
+       if (strcmp(cmd, "run") == 0) {
+               return UHOOKCMD_RUN;
+       }
+       if (strcmp(cmd, "query_val") == 0) {
+               return UHOOKCMD_QUERY_VAL;
+       }
+}
+
+static int parse_result(struct uhook *uhook, char *cmd)
+{
+       printf("The ret of cmd(%s) is %d\n", cmd, uhook->ret);
+       printf("The address of ksymbal(%s) is 0x%x\n",
uhook->fun_name, uhook->addr);
+       printf("The status of ksymbal(%s) run is %s\n", uhook->fun_name,
uhook->status);
+}
+
+static void build_uhook(struct uhook *uhook, char *name)
+{
+       strcpy(uhook->fun_name, name);
+}
+/*
+ * call type:
+ * uhook    --type     run             func
+ * argv[0] argv[1]     argv[2]         argv[3]
+ * */
+int main(int argc, char **argv)
+{
+
+       int uhook_fd = open(DEV_NAME, O_RDWR);
+       struct uhook    uhook;
+       memset(&uhook, 0, sizeof(struct uhook));
+
+       switch(parse_cmd(argv[2])) {
+
+       case UHOOKCMD_QUERY_FUNC:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_QUERY_FUNC, &uhook);
+               parse_result(&uhook, "query");
+               break;
+       case UHOOKCMD_RUN:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_RUN, &uhook);
+               parse_result(&uhook, "run");
+               break;
+       case UHOOKCMD_QUERY_VAL:
+               build_uhook(&uhook, argv[3]);
+               ioctl(uhook_fd, UHOOKCMD_QUERY_VAL, &uhook);
+               parse_result(&uhook, "query val");
+               break;
+       default:
+               printf("Unkown cmd\n");
+       }
+       close(uhook_fd);
+       return 0;
+}
+
--
1.7.7.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
       [not found] ` <20120623040633.GA16278@kroah.com>
@ 2012-06-23  4:18   ` Peiyong Feng
  2012-06-23  4:41     ` Greg KH
  0 siblings, 1 reply; 8+ messages in thread
From: Peiyong Feng @ 2012-06-23  4:18 UTC (permalink / raw)
  To: Greg KH; +Cc: devel, linux-kernel

2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
> On Sat, Jun 23, 2012 at 11:20:35AM +0800, Peiyong Feng wrote:
>> Hi all,
>>
>> This patch implement the uhook kernel driver. Here are some ideals and
>> explanations:
>>
>> 1. What is uhook
>>
>> uhook(userspace kernel hook) means call kernel function from
>> userspace. That is to say, we can
>>
>> write a function in kernel space and call it in userspace while the
>> kernel Image is running. For example:
>
> That's, um, "interesting", but is of course, nothing we can accept into
> the main kernel tree, as I'm sure you can understand.  Otherwise, you
> just created a few thousand undocumented system calls whose behavior
> changes every release which is not something we can accept.
>
> But it is a great hack, very nicely done.  I'm sure that some people
> will like it for debugging, although I'm not quite sure you got all of

Well, is there some other tree I can commit the patch?
> the user/kernel boundry conditions correct, and I know the 32/64bit
> issues aren't handled, which you might want to clean up sometime in the

I am still working on it. The ultimate aim is that the uhook module can process
any funciton and any data type
> future.
>
> greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
  2012-06-23  4:18   ` Peiyong Feng
@ 2012-06-23  4:41     ` Greg KH
  2012-06-23  6:01       ` Peiyong Feng
  0 siblings, 1 reply; 8+ messages in thread
From: Greg KH @ 2012-06-23  4:41 UTC (permalink / raw)
  To: Peiyong Feng; +Cc: devel, linux-kernel

On Sat, Jun 23, 2012 at 12:18:29PM +0800, Peiyong Feng wrote:
> 2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
> > On Sat, Jun 23, 2012 at 11:20:35AM +0800, Peiyong Feng wrote:
> >> Hi all,
> >>
> >> This patch implement the uhook kernel driver. Here are some ideals and
> >> explanations:
> >>
> >> 1. What is uhook
> >>
> >> uhook(userspace kernel hook) means call kernel function from
> >> userspace. That is to say, we can
> >>
> >> write a function in kernel space and call it in userspace while the
> >> kernel Image is running. For example:
> >
> > That's, um, "interesting", but is of course, nothing we can accept into
> > the main kernel tree, as I'm sure you can understand.  Otherwise, you
> > just created a few thousand undocumented system calls whose behavior
> > changes every release which is not something we can accept.
> >
> > But it is a great hack, very nicely done.  I'm sure that some people
> > will like it for debugging, although I'm not quite sure you got all of
> 
> Well, is there some other tree I can commit the patch?

What do you mean by this?

> > the user/kernel boundry conditions correct, and I know the 32/64bit
> > issues aren't handled, which you might want to clean up sometime in the
> 
> I am still working on it. The ultimate aim is that the uhook module can process
> any funciton and any data type

Good luck :)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
  2012-06-23  4:41     ` Greg KH
@ 2012-06-23  6:01       ` Peiyong Feng
  2012-06-23  8:01         ` Cong Wang
  2012-06-23 15:07         ` Greg KH
  0 siblings, 2 replies; 8+ messages in thread
From: Peiyong Feng @ 2012-06-23  6:01 UTC (permalink / raw)
  To: Greg KH; +Cc: devel, linux-kernel

2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
> On Sat, Jun 23, 2012 at 12:18:29PM +0800, Peiyong Feng wrote:
>> 2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
>> > On Sat, Jun 23, 2012 at 11:20:35AM +0800, Peiyong Feng wrote:
>> >> Hi all,
>> >>
>> >> This patch implement the uhook kernel driver. Here are some ideals and
>> >> explanations:
>> >>
>> >> 1. What is uhook
>> >>
>> >> uhook(userspace kernel hook) means call kernel function from
>> >> userspace. That is to say, we can
>> >>
>> >> write a function in kernel space and call it in userspace while the
>> >> kernel Image is running. For example:
>> >
>> > That's, um, "interesting", but is of course, nothing we can accept into
>> > the main kernel tree, as I'm sure you can understand.  Otherwise, you
>> > just created a few thousand undocumented system calls whose behavior
>> > changes every release which is not something we can accept.
>> >
>> > But it is a great hack, very nicely done.  I'm sure that some people
>> > will like it for debugging, although I'm not quite sure you got all of
>>
>> Well, is there some other tree I can commit the patch?
>
> What do you mean by this?

I mean that although the main line kernel cannot accept this patch, and
uhook is very useful to play a rule as a debug tool. Is there some where else
that can hold this tool, and let more people use the uhook?
>
>> > the user/kernel boundry conditions correct, and I know the 32/64bit
>> > issues aren't handled, which you might want to clean up sometime in the
>>
>> I am still working on it. The ultimate aim is that the uhook module can process
>> any funciton and any data type
>
> Good luck :)
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
  2012-06-23  6:01       ` Peiyong Feng
@ 2012-06-23  8:01         ` Cong Wang
  2012-06-23 13:58           ` Peiyong Feng
  2012-06-23 15:07         ` Greg KH
  1 sibling, 1 reply; 8+ messages in thread
From: Cong Wang @ 2012-06-23  8:01 UTC (permalink / raw)
  To: Peiyong Feng; +Cc: Greg KH, devel, linux-kernel

On Sat, Jun 23, 2012 at 2:01 PM, Peiyong Feng
<peiyong.feng.kernel@gmail.com> wrote:
>
> I mean that although the main line kernel cannot accept this patch, and
> uhook is very useful to play a rule as a debug tool.

It depends, we already have kprobe, tracepoint, kgdb, kdump...

> Is there some where else
> that can hold this tool, and let more people use the uhook?

You have github, don't you?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
  2012-06-23  8:01         ` Cong Wang
@ 2012-06-23 13:58           ` Peiyong Feng
  0 siblings, 0 replies; 8+ messages in thread
From: Peiyong Feng @ 2012-06-23 13:58 UTC (permalink / raw)
  To: Cong Wang; +Cc: Greg KH, devel, linux-kernel

2012/6/23 Cong Wang <xiyou.wangcong@gmail.com>:
> On Sat, Jun 23, 2012 at 2:01 PM, Peiyong Feng
> <peiyong.feng.kernel@gmail.com> wrote:
>>
>> I mean that although the main line kernel cannot accept this patch, and
>> uhook is very useful to play a rule as a debug tool.
>
> It depends, we already have kprobe, tracepoint, kgdb, kdump...

May be I am not make myself understood. The uhook is not like kgdb, kprobe or
some other debug tools. As I mentioned in previous mail that we can
run the kernel
ksymbal while kernel is running, not like the kgdb that need some
hardware driver support
(lots of problems occurred when I try kgdb),

uhook is more "soft", it just provide a way that can call kernel
routine or ksymbals Asynchronously.

Easy but efficent. I have used it to develop device drivers, very
nice, and not every platform or board support
kgdb.
>
>> Is there some where else
>> that can hold this tool, and let more people use the uhook?
>
> You have github, don't you?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] Implement uhook(call kernel func from userspace) driver
  2012-06-23  6:01       ` Peiyong Feng
  2012-06-23  8:01         ` Cong Wang
@ 2012-06-23 15:07         ` Greg KH
  1 sibling, 0 replies; 8+ messages in thread
From: Greg KH @ 2012-06-23 15:07 UTC (permalink / raw)
  To: Peiyong Feng; +Cc: devel, linux-kernel

On Sat, Jun 23, 2012 at 02:01:59PM +0800, Peiyong Feng wrote:
> 2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
> > On Sat, Jun 23, 2012 at 12:18:29PM +0800, Peiyong Feng wrote:
> >> 2012/6/23 Greg KH <gregkh@linuxfoundation.org>:
> >> > On Sat, Jun 23, 2012 at 11:20:35AM +0800, Peiyong Feng wrote:
> >> >> Hi all,
> >> >>
> >> >> This patch implement the uhook kernel driver. Here are some ideals and
> >> >> explanations:
> >> >>
> >> >> 1. What is uhook
> >> >>
> >> >> uhook(userspace kernel hook) means call kernel function from
> >> >> userspace. That is to say, we can
> >> >>
> >> >> write a function in kernel space and call it in userspace while the
> >> >> kernel Image is running. For example:
> >> >
> >> > That's, um, "interesting", but is of course, nothing we can accept into
> >> > the main kernel tree, as I'm sure you can understand.  Otherwise, you
> >> > just created a few thousand undocumented system calls whose behavior
> >> > changes every release which is not something we can accept.
> >> >
> >> > But it is a great hack, very nicely done.  I'm sure that some people
> >> > will like it for debugging, although I'm not quite sure you got all of
> >>
> >> Well, is there some other tree I can commit the patch?
> >
> > What do you mean by this?
> 
> I mean that although the main line kernel cannot accept this patch, and
> uhook is very useful to play a rule as a debug tool. Is there some where else
> that can hold this tool, and let more people use the uhook?

Not that I know of.  As someone pointed out, use github to host it on
your own if you want, that is probably the best.

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-06-23 15:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CAN_1RdvqJRig8vZW_gcvNVKYNo7ROmEKxAs7qu1N6XE4+Pspjg@mail.gmail.com>
2012-06-23  3:24 ` [PATCH] Implement uhook(call kernel func from userspace) driver Peiyong Feng
2012-06-23  3:41 ` Peiyong Feng
     [not found] ` <20120623040633.GA16278@kroah.com>
2012-06-23  4:18   ` Peiyong Feng
2012-06-23  4:41     ` Greg KH
2012-06-23  6:01       ` Peiyong Feng
2012-06-23  8:01         ` Cong Wang
2012-06-23 13:58           ` Peiyong Feng
2012-06-23 15:07         ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox