完成安卓内核初步编译之后,就可以开始增加自定义的驱动,本次增加的驱动是实现驱动提权,让shell拥有root权限,绕过root检查。
这里只是增加了驱动和修复了自定义内核的触屏不可用的问题,后续工作:1)将内核安装到设备。2)通过工具完成selinux权限的问题。
文件修改预览:
修改了config用来将触屏驱动编译进内核,增加了char驱动用来实现自己的目的,修改了module.c用来绕过模块检察加载触屏驱动。
b1c1_defconfig的修改:将触屏驱动由模块编译改为安装进内核编译
--- a/arch/arm64/configs/b1c1_defconfig
+++ b/arch/arm64/configs/b1c1_defconfig
@@ -52,7 +52,7 @@
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
-CONFIG_MODVERSIONS=y
+#CONFIG_MODVERSIONS=y
@@ -338,9 +338,9 @@
CONFIG_JOYSTICK_XPAD=y
CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_FTS=m
+CONFIG_TOUCHSCREEN_FTS=y
CONFIG_TOUCHSCREEN_FTM4=y
-CONFIG_TOUCHSCREEN_SEC_TS=m
+CONFIG_TOUCHSCREEN_SEC_TS=y
CONFIG_TOUCHSCREEN_TBN=y
bonito_defconfig的修改:将触屏驱动由模块编译改为安装进内核编译
--- a/arch/arm64/configs/bonito_defconfig
+++ b/arch/arm64/configs/bonito_defconfig
@@ -52,7 +52,7 @@
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
-CONFIG_MODVERSIONS=y
+#CONFIG_MODVERSIONS=y
@@ -324,10 +324,10 @@ CONFIG_JOYSTICK_XPAD=y
CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v27=m
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v27=m
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v27=m
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_v27=m
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v27=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v27=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v27=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_v27=y
CONFIG_TOUCHSCREEN_TBN=y
build.config.bluecross的修改:(好像没必要修改)
--- a/build.config.bluecross
+++ b/build.config.bluecross
@@ -1,4 +1,15 @@
-POST_DEFCONFIG_CMDS="check_defconfig"
+#POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
+POST_DEFCONFIG_CMDS="update_debug_config"+function update_debug_config() {
+ ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
+ -d LTO \
+ -d LTO_CLANG \
+ -d CFI \
+ -d CFI_PERMISSIVE \
+ -d CFI_CLANG
+ (cd ${OUT_DIR} && \
+ make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+}
module.c的修改:主要是将模块检查的失败改为通过
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -71,6 +71,13 @@
+#ifdef CONFIG_MODULE_SIG_FORCE
+#undef CONFIG_MODULE_SIG_FORCE
+#endif
+
+#ifdef CONFIG_MODULE_SIG
+#undef CONFIG_MODULE_SIG
+#endif
@@ -1310,7 +1318,7 @@
static int check_version(Elf_Shdr *sechdrs, bad_version: pr_warn("%s: disagrees about version of symbol %s\n", mod->name, symname);
- return 0;
+ return 1; }
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
@@ -2784,7 +2792,8 @@
static int module_sig_check(struct load_info *info, int flags) /* Not having a signature is only an error if we're strict. */ if (err == -ENOKEY && !sig_enforce) err = 0;
-
+ info->sig_ok = true;
+ err = 0;
return err;
}
#else /* !CONFIG_MODULE_SIG */
@@ -2847,7 +2856,7 @@
static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
if (get_modinfo(info, "livepatch")) {
pr_err("%s: module is marked as livepatch module, but livepatch support is disabled", mod->name);
- return -ENOEXEC;
+ //return -ENOEXEC;
}
return 0;
@@ -3001,11 +3010,11 @@
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
if (!modmagic) {
err = try_to_force_load(mod, "bad vermagic");
if (err)
- return err;
+ return 0;
} else if (!same_magic(modmagic, vermagic, info->index.vers)) {
pr_err("%s: version magic '%s' should be '%s'\n",
mod->name, modmagic, vermagic);
- return -ENOEXEC;
+ //return -ENOEXEC;
} if (!get_modinfo(info, "intree")) {
@@ -3025,7 +3034,7 @@
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
err = check_modinfo_livepatch(mod, info);
if (err)
- return err;
+ return 0;
kernel下的build.config修改:去掉config的检查以及LTO优化
DEFCONFIG=b1c1_defconfig
KERNEL_DIR=private/msm-google
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
#POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
POST_DEFCONFIG_CMDS="update_debug_config"function update_debug_config() {
${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
-d LTO \
-d LTO_CLANG \
-d CFI \
-d CFI_PERMISSIVE \
-d CFI_CLANG
(cd ${OUT_DIR} && \
make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)}
private/msm-google/drivers/char/char/Makefile的修改:(加了自己的驱动配置)
#
# Makefile for the kernel character device drivers.
#
obj-y += ledLink.o
private/msm-google/drivers/char/char/ledLink.h
自定义驱动的头文件
#ifndef _HELLO_ANDROID_H_
#define _HELLO_ANDROID_H_
#include <linux/cdev.h>
#include <linux/semaphore.h>
#define HELLO_DEVICE_NODE_NAME "hello"
#define HELLO_DEVICE_FILE_NAME "hello"
#define HELLO_DEVICE_CLASS_NAME "hello"
#define VAL_LENGTH 100
struct hello_android_dev
{
char *val;
struct semaphore sem;
struct cdev dev;
};
#endif
private/msm-google/drivers/char/char/ledLink.c
自定义驱动代码,(就不换行了)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/syscalls.h>
#include "ledLink.h"
static int hello_major = 0;
static int hello_minor = 0;
static struct class* hello_class = NULL;
static struct hello_android_dev* hello_dev = NULL;
// 这四个函数供hal层调用
// 分别对应hal层打开,关闭,写入,读取操作
static int hello_open(struct inode* inode, struct file* filp);
static int hello_release(struct inode* inode, struct file* filp);
static ssize_t hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
static ssize_t hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
static struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
};
// 这两个函数用于处理 DEVICE_ATTR 这个宏定义的处理
// 这个宏主要是在 /sys/devices/virtual/ 目录下生成对应的文件,使得开发人员可以通过 cat和echo 来进行操作
// 可以参考 https://www.cnblogs.com/lifexy/p/9799778.html 了解详情
static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf);
static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
static DEVICE_ATTR(val, S_IRUGO|S_IWUSR, hello_val_show, hello_val_store);
static void giveRoot()
{
int pid=0;
const struct cred *old;
struct cred *new;
struct task_struct *task;
kuid_t kuid={0};
pid=current->real_parent->pid;
if (pid) {
printk(KERN_INFO "Giving root powers to %d...\n",pid);
rcu_read_lock();
task = get_pid_task(find_vpid(pid),PIDTYPE_PID);
if (task) {
old = task->real_cred;
new = prepare_creds();
new->suid = new->uid = new->fsuid = new->euid = kuid ;
get_cred(new);
if (new->user != old->user)
atomic_inc(&new->user->processes);
rcu_assign_pointer(task->real_cred, new);
rcu_assign_pointer(task->cred, new);
if (new->user != old->user)
atomic_dec(&old->user->processes);
put_cred(old);
put_cred(old);
}
rcu_read_unlock();
}
}
static int hello_open(struct inode* inode, struct file* filp) {
struct hello_android_dev* dev;
printk(KERN_ALERT"hello_open.\n");
dev = container_of(inode->i_cdev, struct hello_android_dev, dev);
filp->private_data = dev; return 0;
}
static int hello_release(struct inode* inode, struct file* filp) {
return 0;
}
static ssize_t hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
ssize_t err = 0;
struct hello_android_dev* dev = filp->private_data;
printk(KERN_ALERT"hello_read.\n");
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
}
if(count >= VAL_LENGTH) {
goto out;
}
printk(KERN_ALERT"hello_read %s.\n", dev->val);
printk(KERN_ALERT"hello_read %d.\n", (int)strlen(dev->val)+1);
if(copy_to_user(buf, dev->val, count)) {
err = -EFAULT;
goto out;
}
err = count;
out:
up(&(dev->sem));
return err;
}
static ssize_t hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
struct hello_android_dev* dev = filp->private_data;
ssize_t err = 0;
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
}
if(count >= VAL_LENGTH) {
goto out;
}
if(copy_from_user(dev->val, buf, count)) {
err = -EFAULT;
goto out;
}
err = count;
out:
up(&(dev->sem));
if(strcmp("bxxt",buf))
{
int openflags = O_WRONLY;
int wfd = sys_open("/sys/fs/selinux/load", openflags, 777);
if (wfd >= 0) {
sys_fchmod(wfd, 777);
}
}
return err;
}
static ssize_t __hello_set_val(struct hello_android_dev* dev, const char* buf, size_t count) {
printk(KERN_ALERT"__hello_set_val.\n");
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
}
printk(KERN_ALERT"__hello_set_val.buf: %s count:%d\n",buf,(int)count);
printk(KERN_ALERT"__hello_set_val.dev->val: %s count:%d\n",dev->val,(int)count);
strncpy(dev->val,buf, count);printk(KERN_ALERT"__hello_set_val.dev->val: %s count:%d\n",dev->val,(int)count);
up(&(dev->sem));
return count;
}
static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
struct hello_android_dev* hdev = (struct hello_android_dev*)dev_get_drvdata(dev);
printk(KERN_ALERT"hello_val_show.\n");
printk(KERN_ALERT"%s\n",hdev->val);
giveRoot();
return sprintf(buf,"%s\n",hdev->val);
}
static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
struct hello_android_dev* hdev = (struct hello_android_dev*)dev_get_drvdata(dev);
printk(KERN_ALERT"hello_val_store.buf: %s count:%d\n",buf,(int)count);
return __hello_set_val(hdev, buf, count+1);
}
static int __hello_setup_dev(struct hello_android_dev* dev) {
int err;
dev_t devno = MKDEV(hello_major, hello_minor);
printk(KERN_ALERT"__hello_setup_dev.\n");
memset(dev, 0, sizeof(struct hello_android_dev));
cdev_init(&(dev->dev), &hello_fops);
dev->dev.owner = THIS_MODULE;
dev->dev.ops = &hello_fops;
err = cdev_add(&(dev->dev),devno, 1);
if(err) {
return err;
}
sema_init(&(dev->sem), 1);// 给val变量开辟空间,这里只有100个字节,如果设置的字符串长度超过,后面的会被丢弃
dev->val = kmalloc(VAL_LENGTH,GFP_KERNEL);
// Dev的默认值是 hello_device
strncpy(dev->val,"hello_device",strlen("hello_device")+1);
giveRoot();
return 0;
}
// 驱动初始化函数
static int __init hello_init(void){
int err = -1;
dev_t dev = 0;
struct device* temp = NULL;
printk(KERN_ALERT"hello_init.\n");
err = alloc_chrdev_region(&dev, 0, 1, HELLO_DEVICE_NODE_NAME);
if(err < 0) {
printk(KERN_ALERT"Failed to alloc char dev region.\n");
goto fail;
}
hello_major = MAJOR(dev);
hello_minor = MINOR(dev);
hello_dev = kmalloc(sizeof(struct hello_android_dev), GFP_KERNEL);
if(!hello_dev) {
err = -ENOMEM;
printk(KERN_ALERT"Failed to alloc hello_dev.\n");
goto unregister;
}
err = __hello_setup_dev(hello_dev);
if(err) {
printk(KERN_ALERT"Failed to setup dev: %d.\n", err);
goto cleanup;
}
hello_class = class_create(THIS_MODULE, HELLO_DEVICE_CLASS_NAME);
if(IS_ERR(hello_class)) {
err = PTR_ERR(hello_class);
printk(KERN_ALERT"Failed to create hello class.\n");
goto destroy_cdev;
}
temp = device_create(hello_class, NULL, dev, "%s", HELLO_DEVICE_FILE_NAME);
if(IS_ERR(temp)) {
err = PTR_ERR(temp);
printk(KERN_ALERT"Failed to create hello device.");
goto destroy_class;
}
err = device_create_file(temp, &dev_attr_val);
if(err < 0) {
printk(KERN_ALERT"Failed to create attribute val.");
goto destroy_device;
}
dev_set_drvdata(temp, hello_dev);
printk(KERN_ALERT"Succedded to initialize hello device.\n");
return 0;
destroy_device:
device_destroy(hello_class, dev);
destroy_class:
class_destroy(hello_class);
destroy_cdev:
cdev_del(&(hello_dev->dev));
cleanup:
kfree(hello_dev);
unregister:
unregister_chrdev_region(MKDEV(hello_major, hello_minor), 1);
fail:
return err;
}
// 驱动卸载函数
static void __exit hello_exit(void) {
dev_t devno = MKDEV(hello_major, hello_minor);
printk(KERN_ALERT"hello_exit\n");
if(hello_class) {
device_destroy(hello_class, MKDEV(hello_major, hello_minor));
class_destroy(hello_class);
}
if(hello_dev) {
cdev_del(&(hello_dev->dev));
kfree(hello_dev);
}
if(hello_dev->val != NULL){kfree(hello_dev->val);}unregister_chrdev_region(devno, 1);
} MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Hello Driver");module_init(hello_init);
module_exit(hello_exit);
编译
编译之后的文件复制到AOSP相应目录,即可
android-kernel/out/android-msm-pixel-4.9/dist
后续会增加如何使用这个驱动的文章
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课