2
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include<linux/sched.h>
#include <asm/uaccess.h>
#include <linux/slab.h>

char *msg;

ssize_t write_proc(struct file *filp,const char *buf,size_t count,loff_t *offp)
{
    copy_from_user(msg,buf,count);
    printk(KERN_INFO "%s",msg);

    return count;
}

struct file_operations proc_fops = {
    write: write_proc
};


int proc_init (void) {
    proc_create("write",0,NULL,&proc_fops);

    return 0;
}

void proc_cleanup(void) {
    remove_proc_entry("write",NULL);
}

MODULE_LICENSE("GPL"); 
module_init(proc_init);
module_exit(proc_cleanup);

When I used the command echo 'hello' > /proc/write Nothing show up on terminal . Can you help me to find mistakes in the code ? The string that I writed on it should have show up on terminal.

Example :

$ echo 'hello' > /proc/write

hello

Mathieu
  • 8,840
  • 7
  • 32
  • 45
anor
  • 43
  • 1
  • 7

1 Answers1

3

Here are some simple modifications on your code:

#define MSG_SIZE (512)
static char *msg;

#define ourmin(a,b) (((a)<(b)) ? (a) : (b))

ssize_t write_proc(struct file *filp,const char *buf,size_t count,loff_t *offp)
{
   unsigned long actual_len = ourmin(count, MSG_SIZE-1);
   memset(msg, 0, MSG_SIZE);
   copy_from_user(msg, buf, actual_len);

   printk(KERN_DEBUG "Got: %s",msg);

   return count;
}

int proc_init (void) {
  // Allocate space for msg
  if ((msg = kmalloc(MSG_SIZE, GFP_KERNEL)) == NULL)
    return -ENOMEM;

  // Should check the output of this too
  proc_create("write",0,NULL,&proc_fops);

  return 0;
}

void proc_cleanup(void) {
    remove_proc_entry("write",NULL);
    kfree(msg);
}

I could retrieve the output in the kernel log (dmesg for instance).

Aif
  • 11,015
  • 1
  • 30
  • 44
  • It would probably be a good idea to add `msg[count] = 0;` after the second `copy_from_user` or else you could see pieces of the text from previous writes. – rodrigo Dec 06 '16 at 11:54
  • 1. no need to write copy_from_user twice 2. there is no error checking, which in particular means the printk discloses kernel memory and in principle can run into an unmapped page and crash 3. the buffer is not necessarily null terminated if copied 4. ENOMEM should be -ENOMEM. errors are negatvive. the *buf arg should be annotated with __user. most importantly though it is clear this is an assignment and OP's familiarity with the C programming language and unix-like systems is insufficient to complete the task. They should be advised to seek help with fellow students. –  Dec 06 '16 at 12:39
  • @employeeofthemonth: there is no call twice, but in the kernel, the `min` macro won't work with a statically defined value. Hence, instead of implementing an other one, I chose to use the if statement. Thanks for pointing out other issues, which I'll correct. – Aif Dec 06 '16 at 12:41
  • I meant the call is written twice which makes the function longer in terms of generated assembly. you can just if (count > MSG_SIZE - 1) count = MSG_SIZE - 1; and be done with it. –  Dec 06 '16 at 12:46