2OF1 · the depletionmode zineLinkedIn · X
← back to the issue

21 September 2010

Writing to kernel ring buffer from userspace

Originally published on the old depletionmode / 2of1 blog (archived copy).

UPDATE: See comments

Linux purists are going to go crazy at this, but I was looking for a way to write to the kernel ring buffer (read by dmesg) from a userspace script.
I’m not going to debate the ‘whys’ – but in short I like having my sys logs for automated system actions (some which are userspace-launched) in one neat place.

I’m not sure if anyone else will find a use for this, but here’s the very small kernel module I wrote to do the job. At the very least it can serve as an example of how to write a kernel module and create a /proc entry:

listing text
/* 
 * userspace-krb linux kernel module
 * (C) 2010, David Kaplan <david@2of1.org>
 *
 * Module to allow writing to the kernel ring buffer from userspace
 *
 */
 
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
 
MODULE_LICENSE( "GPL" );
MODULE_DESCRIPTION( "Interface for userspace writing to kernel ring buffer" );
MODULE_AUTHOR( "David Kaplan");
 
static struct proc_dir_entry *proc_entry;
 
int krb_write( struct file *fp, const char __user *buf,
               unsigned long len, void *data )
{
    int res = len;
    char *msg = kmalloc( len + 1, GFP_ATOMIC );
 
    msg[len] = 0;    /* force \0 termination */
 
    if ( copy_from_user( msg, buf, len ) )
        res = -EFAULT;
    else
        printk( KERN_INFO "%s", msg );
 
    kfree( msg );
 
    return res;
}
 
int krb_init()
{
    if ( ( proc_entry = create_proc_entry( "krb", 0222, NULL ) ) ) {
        proc_entry->write_proc = krb_write;
 
        printk( KERN_INFO "userspace-krb: module loaded.\n" );
        printk( KERN_INFO "userspace-krb: proc entry 'krb' created.\n" );
 
        return 0;
    }
 
    printk( KERN_INFO "userspace-krb: could not create proc entry!\n" );
 
    return -ENOMEM;
}
 
void krb_exit()
{
    remove_proc_entry( "krb", NULL );
    printk( KERN_INFO "userspace-krb: module unloaded.\n" );
}
 
module_init( krb_init );
module_exit( krb_exit );

I probably should have checked to make sure that memory for the msg buffer has been allocated correctly but I couldn’t be bothered. :)

You can also view the latest code, Makefile, etc. in the git repo.

This is how it works:

listing text
$ make -C /usr/src/linux-headers-`uname -r` SUBDIRS=`pwd` modules
make: Entering directory `/usr/src/linux-headers-2.6.35-22-generic'
  CC [M]  /home/dk/code/userspace-krb/userspace-krb.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/dk/code/userspace-krb/userspace-krb.mod.o
  LD [M]  /home/dk/code/userspace-krb/userspace-krb.ko
make: Leaving directory `/usr/src/linux-headers-2.6.35-22-generic'
$ sudo insmod userspace-krb.ko
$ sudo dmesg -c | grep userspace-krb
[86826.875656] userspace-krb: module loaded.
[86826.875658] userspace-krb: proc entry' krb' created.
$ sudo echo "This is written from userspace..." > /proc/krb
$ sudo dmesg -c
[86894.116469] This is written from userspace...

→ end of entry

2/1
@depletionmode
security research & systems engineering