Table of Contents
1. Android root Mount Protect Bypass
1.1. Oppo && Vivo
so easy… fork, fork, fork…
1.2. Huawei MT7 && LOWER
1.2.1. mount check
void submit_bio(int rw, struct bio *bio) { struct task_struct *tsk = current; #ifdef CONFIG_HW_SYSTEM_WR_PROTECT char devname[BDEVNAME_SIZE] = {0}; #endif bio->bi_rw |= rw; /* * If it's a regular read/write or a barrier with data attached, * go through tPGOUT, count); } else { task_io_account_read(bio->bi_size); count_vm_events(PGPGIN, count); } #ifdef CONFIG_HW_SYSTEM_WR_PROTECT if (rw & WRITE) { memset(devname, 0x00, BDEVNAME_SIZE); bdevname(bio->bi_bdev, devname); /* * runmode=factory:send write request to mmc driver. * bootmode=recovery:send write request to mmc driver. * partition is mounted ro: file system will block write request. * root user: send write request to mmc driver. */ if (((strstr(devname, PART_SYSTEM) != NULL) || (strstr(devname, PART_MODEM) != NULL) || (strstr(devname, PART_CUST) != NULL)) && *ro_secure_debuggable) { // ... } } #endif } }
1.2.2. mount bypass:
if (ro_secure_debuggable) { if(*ro_secure_debuggable > KERNEL_ADDR) { ro_secure_debuggable_static = *ro_secure_debuggable; *ro_secure_debuggable_static = 0; } else { *ro_secure_debuggable = 0; } }
1.3. Huawei P10 && UPPER
1.3.1. mount check
void submit_bio(int rw, struct bio *bio) { bio->bi_rw |= rw; /* * If it's a regular read/write or a barrier with data attached, * go through the normal accounting stuff before submission. */ if (bio_has_data(bio)) { unsigned int count; if (unlikely(rw & REQ_WRITE_SAME)) count = bdev_logical_block_size(bio->bi_bdev) >> 9; else count = bio_sectors(bio); if (rw & WRITE) { count_vm_events(PGPGOUT, count); } else { task_io_account_read(bio->bi_iter.bi_size); count_vm_events(PGPGIN, count); } #ifdef CONFIG_HW_SYSTEM_WR_PROTECT if (should_trap_this_bio(rw, bio, count)) return; #endif // ... } } int should_trap_this_bio(int rw, struct bio *bio, unsigned int count) { char *name; if (!(rw & WRITE)) return 0; name = get_bio_part_name(bio); // ... if (likely(!is_protected_partition(name))) return 0; if ((NULL == ro_secure_debuggable) || (0 == *ro_secure_debuggable)) return 0; // ... } static inline char *is_protected_partition(const char *name) { int i; for (i = 0; protected_partitions[i]; i++) { if (!strncmp(name, protected_partitions[i], strlen(protected_partitions[i]) + 1)) { return 1; } } return 0; } /* system write protect flag, 0: disable(default) 1:enable */ static int *ro_secure_debuggable; static char *protected_partitions[] = { "system", "system_a", "system_b", "cust", "cust_a", "cust_b", "vendor", "vendor_a", "vendor_b", "product", "product_a", "product_b", NULL, };
1.3.2. mount bypass
使函数 should_trap_this_bio() 返回 0 即可
echo 0 > /proc/sys_wp_soft HWVTR:/ # cat /proc/kallsyms | grep protected_partitions ffffffc001185ff8 r protected_partitions
只读,不可写入,会崩溃
1.3.3. 缺陷
已有的绕过方案:保护实现位于 software_system_wp.c
重新刷机后发现 mount 后只能写入一次,第二次则失败!
'/dev/block/dm-0' is read-only
经过验证,是 dm-verity 的问题
patch fstab.hi3660 之后就可以正常 mount 以及写入 apk
与 emmc_system_wp.c 实现无关
重启后 apk 生效,与 system-less 模式无关
dm-verity 开启: /dev/block/dm-0 /system ext4 ro,seclabel,relatime,discard,data=ordered 0 0 dm-verity 关闭: /dev/block/bootdevice/by-name/system /system ext4 ro,seclabel,relatime,discard,data=ordered 0 0