Monday 26 May 2014

Write simple character driver exchange data between user space and kernel space – Implementation in read and write calls – Data sizes : byte, integer, and buffer of size ‘n’ • Add support for ‘argument’ verification • Add support for various capabilities – CAP_SYS_ADMIN • Write ioctl to – Get the process id ‘pid’ and ‘process name’ – Get page size – Get the current time – Pass data to the driver (integer and pointer) • User space test application

Assignment 10

• Write simple character driver exchange data between user space and kernel space
– Implementation in read and write calls
– Data sizes : byte, integer, and buffer of size ‘n’
• Add support for ‘argument’ verification
• Add support for various capabilities
– CAP_SYS_ADMIN
• Write ioctl to
– Get the process id ‘pid’ and ‘process name’
– Get page size
– Get the current time
– Pass data to the driver (integer and pointer)
• User space test application

chardriver.c

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
char bufk[100];
int ans;
//structure for information
struct information
{
int pid;
char process_name[20];
int page_size;
char time[20];
}info;
//IOCTL passing structure
#define SAMPLE_IOCTL_MAGIC_NUMBER 'K'
#define SAMPLE_IOCTL_CMD_1 \
_IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 1, struct information)
static ssize_t sample_char_read(struct file * file, char __user * buf, size_t count, loff_t *ppos)
{
char bufk[100]="22";
int f,v;
printk("Kernel Buffer is :%s\n",bufk);
//passing data between user and kernel space
if(count!=4)
{
f=copy_to_user(buf,bufk,count);
if(f){
printk("\n Not success to read");
}
}
else
{
put_user(bufk,buf);
}
//verify permissions for buffer
if(ans=access_ok(VERIFY_READ,buf, sizeof(char)*count))
{
printk("We have read access in read\n");
}
else
{
printk("We dont have read access in read\n");
}
if(ans=access_ok(VERIFY_WRITE,buf, sizeof(char)*count))
{
printk("We have write access in read\n");
}
else
{
printk("We dont have write access in read\n");
}
return 0;
}
static ssize_t sample_char_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
{
int f,v;
int *p;
printk("User Buffer is :%s\n",buf);
//passing data between user and kernel space
if(size!=4)
{
f=copy_from_user(bufk,buf,size);
if(f) {
printk("\n Not success to write");
}
bufk[size]='\0';
printk("kernel:%s\n",bufk);
}
else
{
kstrtol(buf,10,&v);
printk("v=%d\n",v);
}
//verify permissions for buffer
if(ans=access_ok(VERIFY_READ,buf, sizeof(char)*size))
{
printk("We have read access in write\n");
}
else
{
printk("We dont have read access in write\n");
}
if(ans=access_ok(VERIFY_WRITE,buf, sizeof(char)*size))
{
printk("We have write access in write\n");
}
else
{
printk("We dont have write access in write\n");
}
return size;
}
//ioctl to gather information
int sample_char_ioctl (struct file *filp, unsigned int cmd, void* arg)
{
struct information *p=(struct information*)arg;
printk("Sample_char_ioctl\n");
switch (cmd) {
case SAMPLE_IOCTL_CMD_1:
printk("Process ID is=%d\n",p->pid);
printk("Process name is=%s\n",p->process_name);
printk("Current time is=%s\n",p->time);
printk("Page size is=%d\n",p->page_size);
printk("IOCTL CMD1 is done\n");
break;
}
}
int sample_char_open(struct inode *inode, struct file *filp)
{
printk("Sample_char_open\n");
//check capability
if (capable(CAP_SYS_ADMIN))
printk("Not Capable\n");
else
printk(“Capable\n”);
return 0;
}
int sample_char_release(struct inode *inode, struct file *filp)
{
printk("sample_char_release\n");
return 0;
}
static struct file_operations sample_char_fops = {
read: sample_char_read,
write: sample_char_write,
open: sample_char_open,
release: sample_char_release,
unlocked_ioctl:sample_char_ioctl,
};
#define sample_major_number 249
#define max_minors 3
static struct cdev char_cdev;
static dev_t dev;
int init_module(void)
{
int ret = 0;
dev = MKDEV(sample_major_number, 0);
printk("\nLoading the sample char device driver\n");
ret = register_chrdev_region(dev, max_minors, "sample_char");
if (ret)
{
printk("register_chrdev_region Error\n");
goto error;
}
cdev_init(&char_cdev, &sample_char_fops);
ret = cdev_add(&char_cdev, dev, max_minors);
if (ret)
{
printk("cdev_add Error\n");
goto error_region;
}
return 0;
error_region:
unregister_chrdev_region(dev, max_minors);
error:
return ret;
}
void cleanup_module(void)
{
cdev_del(&char_cdev);
unregister_chrdev_region(dev, max_minors);
printk("\nUnloading the sample char device driver\n");
}


test.c

#include<unistd.h>
#include<stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h> // for memset and strlen
#include<time.h>
#include <sys/ioctl.h>
#include<linux/capability.h>
#include<stdlib.h>
struct information
{
int pid;
char process_name[20];
int page_size;
char time[20];
}in;
#define SAMPLE_IOCTL_MAGIC_NUMBER 'K'
#define SAMPLE_IOCTL_CMD_1 \
_IOWR(SAMPLE_IOCTL_MAGIC_NUMBER, 1, struct information)
int main(int argc ,char *argv[])
{
char buf[100],i = 0;
int g,ans;
time_t t;
memset(buf, 0, 100);
printf("Input: %s\n", argv[1]);
strcpy(buf,argv[1]);
int fp = open("/dev/sample_char_10", O_RDWR);
if(fp<0)
{
perror("Not able to open the file");
}
g=write(fp, buf, sizeof(argv[1]));
if(g<0)
{
perror("Write cannot be done");
}
bzero(buf,0);
g=read(fp, buf, sizeof(argv[1]));
if(g<0)
{
perror("Read cannot be done");
}
printf("%s\n",buf);
ans=atoi(buf);
printf("Data from kernel is :%d",ans);
time(&t);
strcpy(in.time,ctime(&t));
in.page_size=getpagesize();
in.pid=getpid();
strcpy(in.process_name,argv[0]);
ioctl(fp, SAMPLE_IOCTL_CMD_1,&in);
//capability
cap_user_header_t cap_header;
cap_user_data_t cap_data;
// struct __user_cap_header_struct cap_header1;
// cap_user_header_t cap_header = &cap_header1;
cap_header = (struct __user_cap_header_struct *)malloc(sizeof(cap_user_header_t));
cap_data = (struct __user_cap_data_struct *)malloc( sizeof(cap_user_data_t));
cap_header->pid = getpid();
cap_header->version = _LINUX_CAPABILITY_VERSION;
if (capget(cap_header, cap_data) < 0)
{
perror("Failed capget");
exit(1);
}
printf("Cap_Effective 0x%x\nCap_permitted 0x%x\nCap_inheritable 0x%x\n",
cap_data->effective,cap_data->permitted, cap_data->inheritable);
cap_data->permitted=CAP_SYS_ADMIN;
cap_data->effective=CAP_SYS_ADMIN;
if (capset(cap_header, cap_data) < 0)
{
perror("Failed capset");
}
printf("Cap_Effective 0x%x\nCap_permitted 0x%x\nCap_inheritable 0x%x\n",
cap_data->effective,cap_data->permitted, cap_data->inheritable);
}


Output :
@ubuntu:~/assign10$ sudo insmod char.ko
@ubuntu:~/assign10$ sudo mknod /dev/sample_char_10 c 249 0
@ubuntu:~/assign10$ sudo chmod 777 /dev/sample_char_10
@ubuntu:~/assign10$ make test

gcc -o test test.c
@ubuntu:~/assign10$ sudo ./test 11111
Input: 11111
11111
Data from kernel is :0Cap_Effective 0xffffffff
Cap_permitted 0xffffffff
Cap_inheritable 0x0
Cap_Effective 0x15
Cap_permitted 0x15
Cap_inheritable 0x0
@ubuntu:~/assign10$

dmesg
[ 2357.535160] Sample_char_open
[ 2357.535170] Capable
[ 2357.535178] User Buffer is :11111
[ 2357.535185] v=11111
[ 2357.535189] We have read access in write
[ 2357.535192] We have write access in write
[ 2357.535198] Kernel Buffer is :22
[ 2357.535201] We have read access in read
[ 2357.535205] We have write access in read
[ 2357.535546] Sample_char_ioctl
[ 2357.535550] Process ID is=21041
[ 2357.535554] Process name is=./test
[ 2357.535557] Current time is=Tue Apr 1 10:33:06 2014
[ 2357.535557]
[ 2357.535563] Page size is=4096
[ 2357.535566] IOCTL CMD1 is done
[ 2357.535791] sample_char_release
[ 2422.377675] Sample_char_open
[ 2422.377691] User Buffer is :11111
[ 2422.377697] v=11111
[ 2422.377701] We have read access in write
[ 2422.377705] We have write access in write
[ 2422.377711] Kernel Buffer is :22
[ 2422.377714] We have read access in read
[ 2422.377718] We have write access in read
[ 2422.378118] Sample_char_ioctl
[ 2422.378123] Process ID is=21054
[ 2422.378127] Process name is=./test
[ 2422.378130] Current time is=Tue Apr 1 10:34:11 2014
[ 2422.378130]
[ 2422.378136] Page size is=4096
[ 2422.378139] IOCTL CMD1 is done
[ 2422.378438] sample_char_release 

No comments: