So, let's create a very simple misc device and let's play with it, doing some reads and writes. Initially, let's define a very simple kernel module (most of the code was taken from here).
#include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <asm/uaccess.h> #define MY_MACIG 'G' #define READ_IOCTL _IOR(MY_MACIG, 0, int) #define WRITE_IOCTL _IOW(MY_MACIG, 1, int) static int used; static char msg[200]; static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset) { return simple_read_from_buffer(buffer, length, offset, msg, 200); } static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t *off) { if (len > 199) return -EINVAL; copy_from_user(msg, buff, len); msg[len] = '\0'; return len; } static int device_open(struct inode *inode, struct file *file) { used++; return 0; } static int device_release(struct inode *inode, struct file *file) { used--; return 0; } char buf[200]; int device_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int len = 200; switch(cmd) { case READ_IOCTL: copy_to_user((char *)arg, buf, 200); break; case WRITE_IOCTL: copy_from_user(buf, (char *)arg, len); break; default: return -ENOTTY; } return len; } static struct file_operations fops = { .owner = THIS_MODULE, .read = device_read, .write = device_write, .open = device_open, .release = device_release, .unlocked_ioctl = device_ioctl }; static struct miscdevice my_miscdev = { .name = "my_device", .mode = S_IRWXUGO, .fops = &fops, }; static int __init cdevexample_module_init(void) { int ret = misc_register(&my_miscdev); if (ret < 0) { printk ("Registering the character device failed\n"); return ret; } printk("create node with mknod /dev/my_device\n"); return 0; } static void __exit cdevexample_module_exit(void) { misc_deregister(&my_miscdev); } module_init(cdevexample_module_init); module_exit(cdevexample_module_exit); MODULE_LICENSE("GPL");
Compile it and insert into Android kernel.
shell@flounder:/ $ su
shell@flounder:/ $ insmod my_module.ko
Now, we can check the new device in /dev:
shell@flounder:/ $ su
shell@flounder:/ $ ls -l /dev
...
crw-rw---- root mtp 10, 23 2015-11-23 18:04 mtp_usb
crw------- root root 10, 0 2015-11-23 18:11 my_device
crw------- root root 10, 36 2015-11-23 18:04 network_latency
crw------- root root 10, 35 2015-11-23 18:04 network_throughput
crw-rw-rw- root root 1, 3 2015-11-23 18:04 null
...
See that the permissions are limited. Don't forget to set it to:
shell@flounder:/ $ chmod 666 /dev/my_device
shell@flounder:/ $ ls -l /dev
...
crw-rw---- root mtp 10, 23 2015-11-23 18:04 mtp_usb
crw-rw-rw- root root 10, 0 2015-11-23 18:11 my_device
crw------- root root 10, 36 2015-11-23 18:04 network_latency
crw------- root root 10, 35 2015-11-23 18:04 network_throughput
crw-rw-rw- root root 1, 3 2015-11-23 18:04 null
...
Now, let's try to do some operations with our device driver:
shell@flounder:/ $ echo "Hello world" > /dev/my_device
shell@flounder:/ $ cat /dev/my_device
You will see the following error on the logcat:
avc: denied { read write } for name="my_device" dev="tmpfs" scontext=u:r:system_app:s0 tcontext
This means that SELinux (yes, Android makes heavy usage of it) also controls the access to device drivers and you cannot read/write from/to your new drive. You have two options: i) disable SELinux in Android (you need to change some kernel options and rebuild it) or ii) add some new rules into SELinux. Let's do the last to learn a bit more :-)
So, we change the following files and give access (read, write, getattr, ioctl, open and create) to our new device /dev/my_device. If you need to restrict the access, you can adapt the policies according to your needs. For more information about SELinux and Android, take a look in this doc (specially the section "Implementation").
external/sepolicy/device.te
type fscklogs, dev_type;
type full_device, dev_type;
type my_device, dev_type;
external/sepolicy/file_contexts
/dev/rproc_user u:object_r:rpmsg_device:s0
/dev/my_device u:object_r:my_device:s0
/dev/snd(/.*)? u:object_r:audio_device:s0
external/sepolicy/app.te
allow appdomain usb_device:chr_file { read write getattr ioctl };
allow appdomain usbaccessory_device:chr_file { read write getattr };
allow appdomain my_device:chr_file { read write getattr ioctl open create };
Now, let's build the Android framework again and flash the device. Everything should work fine.
shell@flounder:/ $ echo "Hello world" > /dev/my_device
shell@flounder:/ $ cat /dev/my_device
Hello world
That's it!! You can also check the following links
- http://www.all-things-android.com/content/understanding-se-android-policy-files
- https://source.android.com/security/selinux/
1 comment:
بطاقات خصم شركة عين
Post a Comment