c - How to send and receive messages from function other than registered callback function in Netlink socket? -


in following kernel module, hooked syscall sys_open, , trying send filename process in userspace using netlink socket, in response process return msg, , according msg, kernel module proceed further.

source code: foo.c

#include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <asm/uaccess.h> #include <asm/cacheflush.h> #include <linux/syscalls.h> #include <linux/delay.h>    // loops_per_jiffy  //===============netlink================= #include <linux/module.h> #include <net/sock.h> #include <linux/netlink.h> #include <linux/skbuff.h>  #define netlink_user 31 struct sock *nl_sk = null; //===============netlink=================  #define cr0_wp 0x00010000   // write protect bit (cr0:16)  /* not taint kernel */ module_license("gpl");  void **syscall_table; unsigned long **find_sys_call_table(void);   long (*orig_sys_open)(const char __user *filename, int flags, int mode); //===============netlink================= static void hello_nl_recv_msg(struct sk_buff *skb) {          struct nlmsghdr *nlh;         int pid;         struct sk_buff *skb_out;         int msg_size;         char *msg = "hello kernel";         int res;          printk(kern_info "entering: %s\n", __function__);          msg_size = strlen(msg);          nlh = (struct nlmsghdr *)skb->data;         printk(kern_info "netlink received msg payload: %s\n", (char *)nlmsg_data(nlh));         pid = nlh->nlmsg_pid; /*pid of sending process */          skb_out = nlmsg_new(msg_size, 0);          if (!skb_out)         {                  printk(kern_err "failed allocate new skb\n");                 return;          }         nlh = nlmsg_put(skb_out, 0, 0, nlmsg_done, msg_size, 0);         netlink_cb(skb_out).dst_group = 0; /* not in mcast group */         strncpy(nlmsg_data(nlh), msg, msg_size);         res = nlmsg_unicast(nl_sk, skb_out, pid);         if (res < 0)                 printk(kern_info "error while sending bak user\n"); } //===============netlink=================  unsigned long **find_sys_call_table() {          unsigned long ptr;         unsigned long *p;          (ptr = (unsigned long)sys_close;                         ptr < (unsigned long)&loops_per_jiffy;                         ptr += sizeof(void *))         {                  p = (unsigned long *)ptr;                  if (p[__nr_close] == (unsigned long)sys_close)                 {                         printk(kern_debug "found sys_call_table!!!\n");                         return (unsigned long **)p;                 }         }          return null; }  long my_sys_open(const char __user *filename, int flags, int mode) {         long ret;          //send filename & response user space app          if(/*user_space_response ==*/ 0)         {                 /*other processing*/                             }         ret = orig_sys_open(filename, flags, mode);         printk(kern_debug "file %s has been opened mode %d\n", filename, mode);          return ret; }  static int __init syscall_init(void) {         int ret;         unsigned long addr;         unsigned long cr0;          syscall_table = (void **)find_sys_call_table();          if (!syscall_table)         {                 printk(kern_debug "cannot find system call address\n");                 return -1;         }          //===============netlink=================         nl_sk = netlink_kernel_create(&init_net, netlink_user, 0, hello_nl_recv_msg, null, this_module);         if (!nl_sk)         {                 printk(kern_debug "error creating socket.\n");                 return -1;         }         //===============netlink=================          cr0 = read_cr0();         write_cr0(cr0 & ~cr0_wp);          addr = (unsigned long)syscall_table;         ret = set_memory_rw(page_align(addr) - page_size, 3);         if(ret)         {                 printk(kern_debug "cannot set memory rw (%d) @ addr %16lx\n", ret, page_align(addr) - page_size);         }         else         {                 printk(kern_debug "3 pages set rw");         }          orig_sys_open = syscall_table[__nr_open];         syscall_table[__nr_open] = my_sys_open;          write_cr0(cr0);          return 0; }  static void __exit syscall_release(void) {         unsigned long cr0;          cr0 = read_cr0();         write_cr0(cr0 & ~cr0_wp);          syscall_table[__nr_open] = orig_sys_open;          write_cr0(cr0);         netlink_kernel_release(nl_sk); }  module_init(syscall_init); module_exit(syscall_release); 

the function 'hello_nl_recv_msg' callback function sends , receives msgs process how can send msg (i.e. filename) function 'my_sys_open' process in user space? , how wait response?

makefile :

obj-m += foo.o  all:             make -c /usr/src/linux-headers-3.2.0-23-generic/ m=$(pwd) modules  clean:      make -c /usr/src/linux-headers-3.2.0-23-generic/ m=$(pwd) clean 

thanks time ;)

  1. how can send msg (i.e. filename) function 'my_sys_open' process in user space?

user-space program should create socket af_netlink, address of socket used send message it. detailed info read man netlink.

  1. and how wait response?

you can use standard mechanism make my_sys_open waiting responce event in hello_nl_recv_msg, e.g. wait_event. simplified code:

/*   * whether responce recieved.  *  * process concurrent open's should map,  * e.g., struct task_struct -> bool.  */ int have_responce = 0; declare_wait_queue_head(responce_waitqueue);     // waitqueue wait responce.  static void hello_nl_recv_msg(struct sk_buff *skb) {     ...     if(<detect responce user program>)     {         have_responce = 1;         wake_up_all(responce_waitqueue);     }     ... }  long my_sys_open(const char __user *filename, int flags, int mode) {     struct sk_buff *skb_out;     ...     have_responce = 0; // clear responce flag     nlmsg_unicast(nl_sk, skb_out, <stored_user_pid>);// send message     wait_event(responce_waitqueue, have_responce); //wait until responce received     .... } 

Comments

Popular posts from this blog

yii2 - Yii 2 Running a Cron in the basic template -

asp.net - 'System.Web.HttpContext' does not contain a definition for 'GetOwinContext' Mystery -

mercurial graft feature, can it copy? -