首页
社区
课程
招聘
[原创]安卓自定义内核-增加驱动-修复触屏
发表于: 2022-12-6 21:32 11546

[原创]安卓自定义内核-增加驱动-修复触屏

2022-12-6 21:32
11546

    完成安卓内核初步编译之后,就可以开始增加自定义的驱动,本次增加的驱动是实现驱动提权,让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_devicestrncpy(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

                  后续会增加如何使用这个驱动的文章



                  [注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

                  收藏
                  免费 4
                  支持
                  分享
                  最新回复 (2)
                  雪    币: 2264
                  活跃值: (3094)
                  能力值: ( LV2,RANK:10 )
                  在线值:
                  发帖
                  回帖
                  粉丝
                  2
                  感谢大佬,正好遇到了这个问题,我去试一试
                  2023-3-16 21:12
                  0
                  雪    币: 1
                  活跃值: (150)
                  能力值: ( LV2,RANK:10 )
                  在线值:
                  发帖
                  回帖
                  粉丝
                  3
                  大佬请问接开发吗?可否留个联系
                  2023-4-1 22:05
                  0
                  游客
                  登录 | 注册 方可回帖
                  返回
                  //