title: How to pass a char *array (belonging to the user address space) to a tasklet or workqueue in a kernel module?
body: <p>I’m writing a device driver. If someone calls the write operation I want it to be deferred (using tasklet or workqueue). The code should be something like that:</p>
  <pre><code>static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off) {
  
        packed_work *the_task;
        the_task = kzalloc(sizeof(packed_work), GFP_ATOMIC);
        if (the_task == NULL) {
           printk(KERN_ERR &quot;%s: tasklet buffer allocation failure\n&quot;, MODNAME);
           return -1;
        }
  
        the_task-&gt;buffer = the_task;
        the_task-&gt;buff = buff;
        the_task-&gt;len = len;
  
        INIT_WORK(&amp;(the_task-&gt;the_work), (void*)deferred_write);
        schedule_work(&amp;the_task-&gt;the_work);
  
        return len;
  }
  
  void deferred_write(struct work_struct *data) {
      
        printk(“the text: %s\n”, container_of(data, packed_work, the_work)-&gt;buff);
  
        //copy_from_user(&amp;(the_object-&gt;stream_content), container_of(data, packed_work, the_work)-&gt;buff, len);
  
        kfree((void*)container_of(data,packed_work,the_work));   
  
  }
  </code></pre>
  <p>And the struct looks like this:</p>
  <pre><code>typedef struct _packed_work{
      void *buffer;
      const char *buff; 
      size_t len;
      struct work_struct the_work;
  } packed_work;
  </code></pre>
  <p>The problem is that the kernel crashes. It crashes even before the copy_from_user (that’s why I commented it). In the deferred_write() I can print the length of the string but not the string itself. Is it a problem because the buffer is in the user space memory?</p>
  <p>I know that, as a workaround, I can copy the user buffer in the task struct (using the copy_from_user() in the function write()) and then use the strcpy() in the deferred_write() function. But I really would like to use the copy_from_user() in deferred_write(). Is it possible? What can I do?</p>