how to access kernel driver from user-space

24
How to Access Kernel Driver from User- space Sheng-Wei, Lin 2015/03/26

Upload: sheng-wei-lin

Post on 15-Aug-2015

45 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: How to Access Kernel Driver from User-space

How to Access Kernel Driver from User-

spaceSheng-Wei, Lin

2015/03/26

Page 2: How to Access Kernel Driver from User-space

Introduction Character Device Input/Output Control Input Device Device Attributes in Sysfs

Outline

Page 3: How to Access Kernel Driver from User-space

Introduction

Architecture of GNU/Linux OS

Page 4: How to Access Kernel Driver from User-space

Character device◦ Accessed as a stream of bytes by means of

filesystem nodes under /dev, such as tty, serial devices.

Device driver – Character Device

Char devcies Major number Minor number

Page 5: How to Access Kernel Driver from User-space

Roles of Major/Minor Number

/dev/devicen

Process

kobj_map

char driver

physical device

user space

kernel space

open()

sys_open()

Major number used to match the corresponding driver

Minor number used to identify devices

Page 6: How to Access Kernel Driver from User-space

struct cdev {struct kobject kobj;struct module *owner;const struct file_operations *ops;struct list_head list;dev_t dev;unsigned int count;

};

Structure of Character Device

Page 7: How to Access Kernel Driver from User-space

struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *filp, char __user *buf, size_t count, loff_t *ppos);ssize_t (*write) (struct file *filp, const char __user *buf, size_t count, loff_t *ppos);ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*aio_fsync) (struct kiocb *, int datasync);int (*fasync) (int, struct file *, int);

…………………………………….};

File Operations

Page 8: How to Access Kernel Driver from User-space

#include <asm/uaccess.h> /* Copy data from user space to kernel space. */ unsigned long copy_from_user (void *to, const void *from,

unsigned long count) /* Copy a block of data into user space. */ unsigned long copy_to_user(void *to, const void *from,

unsigned long count) /* Write a simple value into user space. */ int put_user(x, ptr) , __put_user(x, ptr) /* Get a simple variable from user space. */ int get_user(x, ptr), __get_user(x, ptr)

Data Copy between Kernel-space & User-space

Process Virtual Space

Page 9: How to Access Kernel Driver from User-space

#include <asm/uaccess.h> /* Copy data from user space to kernel space. */ unsigned long copy_from_user (void *to, const void *from,

unsigned long count) /* Copy a block of data into user space. */ unsigned long copy_to_user(void *to, const void *from,

unsigned long count) /* Write a simple value into user space. */ int put_user(x, ptr) , __put_user(x, ptr) /* Get a simple variable from user space. */ int get_user(x, ptr), __get_user(x, ptr)

Data Copy between Kernel-space & User-space

Process Virtual Space

without access_ok() check

Page 10: How to Access Kernel Driver from User-space

Flow of Data Read

0xC0000000

0xFFFFFFFF

0x00000000

1GB

3GB

datacdev->ops->read()

read()

sys_read()kernel space

user spaceProcess Virtual

Space

Page 11: How to Access Kernel Driver from User-space

Flow of Data Read

0xC0000000

0xFFFFFFFF

0x00000000

1GB

3GB data

datacdev->ops->read()

read()

sys_read()

copy_to_user()

Process Virtual Space

kernel space

user space

Page 12: How to Access Kernel Driver from User-space

#include <linux/cdev.h>#include <linux/types.h>#include <linux/device.h>

/* register a range of char device numbers */ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char

*name) /* initialize a cdev structure */ void cdev_init(struct cdev *cdev, const struct file_operations *fops) /* add a char device to the system */ int cdev_add(struct cdev *p, dev_t dev, unsigned count) /* create a struct class structure */ int class_create(struct module *owner, const char *name) /* creates a device and registers it with sysfs */ struct device *device_create(struct class *class, struct device *parent,

dev_t devt, void *drvdata, const char *fmt, ...)

Registration of Character Device

Page 13: How to Access Kernel Driver from User-space

IOCTL◦ A system call that offers a way to access device-

specific commands

Input/Output Control (IOCTL)

ioctl(int fd, int cmd, …)

long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long arg);

User-space

Kernel-space

Page 14: How to Access Kernel Driver from User-space

struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long arg);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*aio_fsync) (struct kiocb *, int datasync);int (*fasync) (int, struct file *, int);

…………………………………….};

File Operations

Page 15: How to Access Kernel Driver from User-space

Command format

android/kernel/Documentation/ioctl/ioctl-number.txt Macros for command setup /* An ioctl with no parameters */

◦ IO(type, nr) /* An ioctl with read parameters (copy_to_user) */

◦ _IOR(type, nr, datatype) /* An ioctl with write parameters (copy_from_user) */

◦ _IOW(type, nr,datatype) /* An ioctl with both write and read parameters */

◦ _IOWR(type, nr, datatype)

IOCTL Command

dir size type nr

MSB LSB

2 bit 14 bit 8 bit 8bit

Page 16: How to Access Kernel Driver from User-space

An event-driven device that reports input events to user applications through character devices in the /dev/input directory◦ E.g., button, mouse, joystick.

Device driver – Input Device

Page 17: How to Access Kernel Driver from User-space

Input Subsystem

Page 18: How to Access Kernel Driver from User-space

input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

android/kernel/Documentation/input/event-codes.txt EV_KEY:

◦ Used to describe state changes of keyboards, buttons, etc.◦ e.g., KEY_POWER, KEY_VOLUMEUP, KEY_VOLUMEDOWN

EV_ABS:◦ Used to describe absolute axis value changes◦ e.g., ABS_X, ABS_Y, ABS_Z

EV_REL:◦ Used to describe relative axis value changes◦ e.g., REL_X, REL_Y, REL_Z

z

Event Types & Codes

Page 19: How to Access Kernel Driver from User-space

Sysfs◦ A virtual filesystem that contains information

about device, drivers and buses as seen from the kernel.

Device attribute◦ Exported for kobjects in the form of regular files in

sysfs. Sysfs forwards file I/O operations to methods defined for the attributes, providing a means to read and write kernel attributes.

Device Attributes in Sysfs

Page 20: How to Access Kernel Driver from User-space

#include <linux/device.h>

/* Declare a device attribute */ DEVICE_ATTR(_name, _mode, _show, _store) \

struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)/* Store attributes into array */ static struct attribute * attrs[] = {…};/* Declare a attribute group */ struct attribute_group { const char *name; umode_t (*is_visible)(struct kobject *, struct attribute *, int); struct attribute **attrs;};/* Given a directory kobject, create an attribute group */ int sysfs_create_group(struct kobject *kobj,

const struct attribute_group *grp);

Device Attributes Setup

Page 21: How to Access Kernel Driver from User-space

What does the file operation should be used if we want to enable a serial character device ?

Q1

Page 22: How to Access Kernel Driver from User-space

What does the file operation should be used if we want to enable a serial character device ?

-> IOCTL

Q1

Page 23: How to Access Kernel Driver from User-space

How does the kernel identify the corresponding

driver when opening /dev/tty0 ?

Q2

Page 24: How to Access Kernel Driver from User-space

How does the kernel identify the corresponding

driver when opening /dev/tty0 ?-> Major number

Q2

/dev/devicen

Process

kobj_map

device driver

physical device

user space

kernel space

open()

sys_open()Major number used to match the corresponding driver

Minor number used to identify devices