title: Linux Kernel Module unix domain sockets
body: <p>I'm trying to share data between kernel and user space. The ultimate goal is to port it to Android, so I'm using unix domain sockets. (I don't know if this is the best option).</p>
  
  <p>I have a kernel module acting as socket client and a c program acting as socket server. And vice-versa, a kernel module acting as socket server and a c program acting as socket client.</p>
  
  <p>Programs are very simple. Servers just send a string to clients and they print it.</p>
  
  <p>I run <strong>server_user.c</strong> and then I try to insert <strong>client_module.ko</strong> using insmod. I get the following error:</p>
  
  <pre><code>Kernel panic - not syncing: stack - protector: Kernel stack is corrupted in: ffffffffa0005157
  
  drm-kms-helper: panic occurred, switching back to text console 
  </code></pre>
  
  <p>What's wrong?</p>
  
  <p>Module Server</p>
  
  <pre><code>#include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  #include &lt;linux/socket.h&gt;
  #include &lt;linux/net.h&gt;
  #include &lt;linux/un.h&gt;
  #include &lt;net/sock.h&gt;
  
  #define SOCK_PATH   "/tmp/usocket"
  #define LISTEN      10
  
  struct socket *sock = NULL;
  struct socket *newsock = NULL;
  
  static int __init server_module_init( void ) {
  
    int retval;
    char* string = "hello_world";
  
    struct sockaddr_un addr;
    struct msghdr msg;
    struct iovec iov;
    mm_segment_t oldfs;
  
    // create
    retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &amp;sock);
  
    memset(&amp;addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, SOCK_PATH);
  
    // bind
    retval = sock-&gt;ops-&gt;bind(sock,(struct sockaddr *)&amp;addr, sizeof(addr));
  
    // listen
    retval = sock-&gt;ops-&gt;listen(sock, LISTEN);
  
    //accept
    retval = sock-&gt;ops-&gt;accept(sock, newsock, 0);
  
    //sendmsg
    memset(&amp;msg, 0, sizeof(msg));
    memset(&amp;iov, 0, sizeof(iov));
  
    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &amp;iov;
    msg.msg_iov-&gt;iov_base = string;
    msg.msg_iov-&gt;iov_len = strlen(string)+1;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;
  
    oldfs = get_fs();
    set_fs(KERNEL_DS);
  
    retval = sock_sendmsg(newsock, &amp;msg, strlen(string)+1);
  
    set_fs(oldfs);
  
    return 0;
  }
  
  static void __exit server_module_exit( void ) {
    printk(KERN_INFO "Exit usocket.");
  }
  
  module_init( server_module_init );
  module_exit( server_module_exit );
  MODULE_LICENSE("GPL");
  </code></pre>
  
  <p>Module Client</p>
  
  <pre><code>#include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  #include &lt;linux/un.h&gt;
  #include &lt;linux/net.h&gt;
  #include &lt;net/sock.h&gt;
  #include &lt;linux/socket.h&gt;
  
  #define SOCK_PATH   "/tmp/usocket"
  #define MAX     100
  
  struct socket *sock = NULL;
  
  
  static int __init client_module_init( void ) {
  
    int retval;
    char str[MAX];
  
    struct sockaddr_un addr;
    struct msghdr msg;
    struct iovec iov;
    mm_segment_t oldfs;
  
    printk(KERN_INFO "Start client module.\n");
  
    // create
    retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &amp;sock); 
  
    // connect
    memset(&amp;addr, 0, sizeof(addr));  
    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, SOCK_PATH);
  
    retval = sock-&gt;ops-&gt;connect(sock, (struct sockaddr *)&amp;addr, sizeof(addr), 0);
  
    // recvmsg
  
    memset(&amp;msg, 0, sizeof(msg));
    memset(&amp;iov, 0, sizeof(iov));
  
    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &amp;iov;
    msg.msg_iovlen = 1;
    msg.msg_iov-&gt;iov_base= str;
    msg.msg_iov-&gt;iov_len= strlen(str)+1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;
  
    oldfs = get_fs();
    set_fs(KERNEL_DS);
  
    retval = sock_recvmsg(sock, &amp;msg, strlen(str)+1, 0);
  
    set_fs(oldfs);
  
    // print str
    printk(KERN_INFO "client module: %s.\n",str);
  
    // release socket
    sock_release(sock);
  
    return 0;
  }
  
  static void __exit client_module_exit( void )
  {
    printk(KERN_INFO "Exit client module.\n");
  }
  
   module_init( client_module_init );
   module_exit( client_module_exit );
   MODULE_LICENSE("GPL");
  </code></pre>
  
  <p>User Server</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/un.h&gt;
  
  #define SOCK_PATH "/tmp/usocket"
  
  int send_msg_to_client(int socketfd, char* data) {
  
    struct msghdr msg;
    struct iovec iov;
    int s;
  
    memset(&amp;msg, 0, sizeof(msg));
    memset(&amp;iov, 0, sizeof(iov));
  
    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    iov.iov_base = data;
    iov.iov_len = strlen(data)+1;
    msg.msg_iov = &amp;iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;
  
    s = sendmsg(socketfd, &amp;msg, 0);
  
    printf("after send - iov_base: %s, length: %d\n", (char *) msg.msg_iov-&gt;iov_base, (int) strlen(msg.msg_iov-&gt;iov_base));
  
    if(s &lt; 0){
      perror("sendmsg");
      return 0;
    }
  
    return s;
  }
  
  
  int main(int argc, char* argv[])
  {
  
          if (argc != 2) {
            printf("Usage: $ %s &lt;string&gt;\n",argv[0]);
            return 0;
          }
  
      int s, s2, len, slen;
      socklen_t t;
      struct sockaddr_un local, remote;
      char* data = argv[1];
  
      printf("print data: %s\n",data);
  
      if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
          perror("socket");
          exit(1);
      }
  
      memset(&amp;local, 0, sizeof(local));
      local.sun_family = AF_UNIX;
      strcpy(local.sun_path, SOCK_PATH);
  
      unlink(local.sun_path);
  
      len = strlen(local.sun_path) + sizeof(local.sun_family);
      if (bind(s, (struct sockaddr *)&amp;local, len) == -1) {
          perror("bind");
          exit(1);
      }
  
      if (listen(s, 5) == -1) {
          perror("listen");
          exit(1);
      }
  
      printf("Waiting for a connection...\n");
  
      t = sizeof(remote);
      if ((s2 = accept(s, (struct sockaddr *)&amp;remote, &amp;t)) == -1) {
          perror("accept");
          exit(1);
      }
  
      printf("Connected.\n");
  
      slen = send_msg_to_client(s2, data);
  
      if(slen &lt; 0)
          perror("send");
  
      close(s2);
  
      return 0;
  }
  </code></pre>
  
  <p>User Client</p>
  
  <pre><code>#include &lt;unistd.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/un.h&gt;
  
  #define SOCK_PATH "/tmp/usocket"
  #define MAX 100
  
  int recv_msg_from_server(int socketfd, char data[MAX]) {
  
    struct msghdr msg;
    struct iovec iov;
    int s;
  
    memset(&amp;msg, 0, sizeof(msg));
    memset(&amp;iov, 0, sizeof(iov));
  
    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    iov.iov_base = data;
    iov.iov_len = MAX;
    msg.msg_iov = &amp;iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;
  
  
    s = recvmsg(socketfd, &amp;msg, 0);
  
    printf("after recv - iov_base: %s, length: %d\n", (char *) msg.msg_iov-&gt;iov_base, (int) strlen(msg.msg_iov-&gt;iov_base));
  
    if(s &lt; 0){
      perror("recvmsg");
    }
  
    return s;
  }
  
  
  int main(void)
  {
      int s, len, slen;
      struct sockaddr_un remote;
      char data[MAX];
  
      if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
              perror("socket");
              exit(1);
          }
  
      printf("Trying to connect...\n");
  
      memset(&amp;remote, 0, sizeof(remote));
  
      remote.sun_family = AF_UNIX;
      strcpy(remote.sun_path, SOCK_PATH);
      len = strlen(remote.sun_path) + sizeof(remote.sun_family);
  
      if (connect(s, (struct sockaddr *)&amp;remote, len) == -1) {
              perror("connect");
              exit(1);
          }
  
      printf("Connected.\n");
  
      slen = recv_msg_from_server(s, data);
  
      if (slen &lt; 0) {
          perror("recvmsg");
      }
  
      //printf("print data received &gt; %s\n", data);
  
      close(s);
  
      return 0;
  }
  </code></pre>