sábado, 22 de outubro de 2011

Character device Hello World

This is a little character device hello World, more
information on code.

/*
 * file: gkos_char_device.c
 *
 * Desc: A simple device that
 *      echos a message when read,
 *      write method not implemented
 *
 *      This was made on top of 
 *      LDD and LKMPG examples 
 *      
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "gkos_char_device"


/*
 * Prototypes 
 */
int init_module(void);
void cleanup_module(void);
static int dev_open(struct inode *inode, struct file *);
static int dev_release(struct inode *inode, struct file *);
static ssize_t dev_read(struct file *fp, char *buf, size_t len, loff_t *off);
static ssize_t dev_write(struct file *, const char *buf, size_t len, 
                loff_t *off);
static int dev_init(void);

/*
 * Our variables, @use_counter
 * will block concurrenty opens.
 * @buffer is the message and
 * @buffer_len the lenght of @buffer (duh)
 */
static char use_counter = 0;
static char buffer[] = "Hello character device world\n";
static int buffer_len = sizeof(buffer);

static dev_t dev;
static struct cdev *cdevp;


static struct file_operations fops = {
        .owner = THIS_MODULE,
        .read = dev_read,
        .write = dev_write,
        .open = dev_open,
        .release = dev_release
};

/*
 * Any device specific initialization
 * goes here. Its called at bottom of init_module()
 */
static int dev_init(void)
{
        return 0;
}

/*
 * Called when device is opened
 */
static int dev_open(struct inode *inode, struct file *fp)
{
        if (use_counter)
                return -EBUSY;
        use_counter++;
        try_module_get(THIS_MODULE);
        return 0;
}

/* 
 * Called when device is released. The device is
 * released when there is no process using it.
 */
static int dev_release(struct inode *inode, struct file *fp)
{
        use_counter--;
        module_put(THIS_MODULE);
        return 0;
}


/*
 * @off controls
 * the "walk" through our buffer, is whith @off
 * that we say to user where is stoped.
 * @len is how much bytes to read. I almost ignore it.
 * I just check if is greater than 0.
 *
 * Called when device is read. 
 * This method will read one, and only one byte per call,
 * If @off is longer than my buffer size or len is not
 * greater than 0 it returns 0, otherwise I copy one byte
 * to user buffer and returns the bytes readed, so 1.
 */
static ssize_t dev_read(struct file *fp, char *buf, size_t len, loff_t *off)
{
        if (*off >= buffer_len || len <= 0)
                return 0;

        if (copy_to_user(buf, &buffer[*off], 1u))
                        return -EFAULT;

        (*off)++;
        return 1;
}


/*
 * Not implemented at all
 */
static ssize_t dev_write(struct file *fp, const char *buf, size_t len, 
                loff_t *off)
{
        return -ENOSYS;
}

/*
 * Called when module is load
 */
int init_module(void)
{
        int error;

        /* Alloc a device region */
        error = alloc_chrdev_region(&dev, 1, 1, DEVICE_NAME);
        if (error) 
                goto error_out;

        /* Registring */
        cdevp = cdev_alloc();
        if (!cdevp) 
                return -ENOMEM; 

        /* Init it! */
        cdev_init(cdevp, &fops); 

        /* Tell the kernel "hey, I'm exist" */
        error = cdev_add(cdevp, dev, 1);
        if (error < 0) 
                goto error_out;

        printk(KERN_INFO DEVICE_NAME " registred with major %d\n", MAJOR(dev));
        printk(KERN_INFO DEVICE_NAME " do: `mknod /dev/%s c %d %d' to create "
                        "the device file\n", 
                        DEVICE_NAME, MAJOR(dev), MINOR(dev)); 

        /* Device initialization isn't needed yet */
        if (dev_init())
                goto error_out;

        return 0;

error_out:
        return -EFAULT;
}

void cleanup_module(void)
{
        cdev_del(cdevp);
}

MODULE_LICENSE("GPL");

Makefile:
obj-m += gkos_char_device.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
 
clean:
 rm *.ko *.o *.mod.c *.mod.o

Building and Running:

sexta-feira, 21 de outubro de 2011

Perl assembly generator

I wrote a little perl script that receives input and creates an x86 assembly program. This program put all data on stack and then print it using printf c function. Useless but cool
#!/usr/bin/perl

use warnings;
use strict;

undef $/;
my $input = <>

$input = unpack("H*", $input);
my @integers;

while (length($input) > 8) {
 my $str = substr($input, 0, 8);
 $str =~ s/(.{2})(.{2})(.{2})(.{2})/$4$3$2$1/;
 push(@integers, ("0x".$str));
 $input = substr($input, 8);
}

my $buf = "";
while (length($input) > 0) {
 $buf .= substr($input, -2);
 $input = substr($input, 0, -2);
}

push(@integers, sprintf("0x%08x", hex($buf)));
my $stck_deep = ($#integers + 1) * 4;

print <<EOS
        .section        .text.startup,"ax",\@progbits
        .globl  main
        .type   main, \@function
main:
        pushl   %ebp
        movl    %esp, %ebp

 subl \$$stck_deep, %esp

 movl \$$integers[0], (%esp)
EOS
;

for my $i (1 .. $#integers) {
 printf("\tmovl \$%s, %d(%%esp)\n", $integers[$i], $i * 4); 
} 

print <<EOS
 movl \$0x0, $stck_deep(%esp)
 
 pushl %esp
 call printf
 popl %eax

 addl \$$stck_deep, %esp


 xorl %eax, %eax
 leave
 ret
EOS

;

Here is a try:
https://ideone.com/cuvXe
https://ideone.com/2oA9q
[]'s

terça-feira, 11 de outubro de 2011

Pickshit game ported to autotools

I have made just a exercise of applying autotools to my Pick stick game


Here is the "autotool'ed" source

[]'s

Procfs hello world

Fuck you world... I will learn kernel, getting payed or not!!


Here is a simple procfs hello world


The source (proc2.c)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>

static struct proc_dir_entry *proc_file;

int procfile_read(char *buf, char **buf_location, off_t offset,
 int buf_len, int *eof, void *data)
{
 return sprintf(buf, "Hello Word\n"); 
}

#define PROC_FILE_NAME "hello"
int init_module()
{
 proc_file = create_proc_entry(PROC_FILE_NAME, 0644, NULL);
 if (!proc_file) { 
  remove_proc_entry(PROC_FILE_NAME, NULL);
  return -ENOMEM;
 } 
 proc_file->read_proc = procfile_read;
 proc_file->mode = 0644;
 proc_file->uid = 0;
 proc_file->gid = 0;
 proc_file->size = 37;
 return 0;
}


void cleanup_module()
{
 remove_proc_entry(PROC_FILE_NAME, NULL);
}

The Makefile
obj-m += proc2.o

all:
 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Compiling and running


Cheers :-P