adb root/adb reboot/adb remount实现简易剖析
本帖最后由 元始天尊 于 2016-5-10 20:07 编辑/system/core/adb/commandline.c
int adb_commandline(int argc, char **argv){
...............//总分支
if(!strcmp(argv, "remount") || !strcmp(argv, "reboot")
|| !strcmp(argv, "reboot-bootloader")
|| !strcmp(argv, "tcpip") || !strcmp(argv, "usb")
|| !strcmp(argv, "root")) {
char command;
if (!strcmp(argv, "reboot-bootloader"))
snprintf(command, sizeof(command), "reboot:bootloader");
else if (argc > 1)
snprintf(command, sizeof(command), "%s:%s", argv, argv);
else
snprintf(command, sizeof(command), "%s:", argv);
int fd = adb_connect(command);
if(fd >= 0) {
read_and_dump(fd);
adb_close(fd);
return 0;
}
fprintf(stderr,"error: %s\n", adb_error());
return 1;
}
}
//service.c
int service_to_fd(const char *name)
else if(!strncmp(name, "remount:", 8)) {
ret = create_service_thread(remount_service, NULL);
} else if(!strncmp(name, "reboot:", 7)) {
void* arg = strdup(name + 7);
if(arg == 0) return -1;
ret = create_service_thread(reboot_service, arg);
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread(restart_root_service, NULL);
}
/remount_service.c
static int remount_system()
{
char *dev;
if (system_ro == 0) {
return 0;
}
dev = find_mount("/system");
if (!dev)
return -1;
system_ro = mount(dev, "/system", "none", MS_REMOUNT, NULL);
free(dev);
return system_ro;
}
/reboot_service
void reboot_service(int fd, void *arg)
{
char buf;
int pid, ret;
sync();
/* Attempt to unmount the SD card first.
* No need to bother checking for errors.
*/
pid = fork();
if (pid == 0) {
/* ask vdc to unmount it */
execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
getenv("EXTERNAL_STORAGE"), "force", NULL);
} else if (pid > 0) {
/* wait until vdc succeeds or fails */
waitpid(pid, &ret, 0);
}
ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
if (ret < 0) {
snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
writex(fd, buf, strlen(buf));
}
free(arg);
adb_close(fd);
}
//system/core/libcutils/android_reboot.c
int android_reboot(int cmd, int flags, char *arg)
{
int ret;
if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
sync();
if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
remount_ro();
switch (cmd) {
case ANDROID_RB_RESTART:
ret = reboot(RB_AUTOBOOT);
break;
case ANDROID_RB_POWEROFF:
ret = reboot(RB_POWER_OFF);
break;
case ANDROID_RB_RESTART2:
ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, arg);
break;
default:
ret = -1;
}
return ret;
}
//bionic/libc/arch-arm/syscalls/__reboot.S
ENTRY(__reboot)
mov ip, r7
ldr r7, =__NR_reboot
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(__reboot)
/root
void restart_root_service(int fd, void *cookie)
{
char buf;
char value;
if (getuid() == 0) {
snprintf(buf, sizeof(buf), "adbd is already running as root\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
} else {
property_get("ro.debuggable", value, "");
if (strcmp(value, "1") != 0) {
snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
return;
}
property_set("service.adb.root", "1");
snprintf(buf, sizeof(buf), "restarting adbd as root\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
}
}
static int should_drop_privileges() {
#ifndef ALLOW_ADBD_ROOT
return 1;
#else /* ALLOW_ADBD_ROOT */
int secure = 0;
char value;
/* run adbd in secure mode if ro.secure is set and
** we are not in the emulator
*/
property_get("ro.kernel.qemu", value, "");
if (strcmp(value, "1") != 0) {
property_get("ro.secure", value, "1");
if (strcmp(value, "1") == 0) {
// don't run as root if ro.secure is set...
secure = 1;
// ... except we allow running as root in userdebug builds if the
// service.adb.root property has been set by the "adb root" command
property_get("ro.debuggable", value, "");
if (strcmp(value, "1") == 0) {
property_get("service.adb.root", value, "");
if (strcmp(value, "1") == 0) {
secure = 0;
}
}
}
}
return secure;
#endif /* ALLOW_ADBD_ROOT */
}
int adb_main(int is_daemon, int server_port){
.....................
if (should_drop_privileges()) {
struct __user_cap_header_struct header;
struct __user_cap_data_struct cap;
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
exit(1);
}
/* add extra groups:
** AID_ADB to access the USB driver
** AID_LOG to read system logs (adb logcat)
** AID_INPUT to diagnose input issues (getevent)
** AID_INET to diagnose network issues (netcfg, ping)
** AID_GRAPHICS to access the frame buffer
** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
** AID_SDCARD_R to allow reading from the SD card
** AID_SDCARD_RW to allow writing to the SD card
** AID_MOUNT to allow unmounting the SD card before rebooting
** AID_NET_BW_STATS to read out qtaguid statistics
*/
gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
AID_MOUNT, AID_NET_BW_STATS };
if (setgroups(sizeof(groups)/sizeof(groups), groups) != 0) {
exit(1);
}
/* then switch user and group to "shell" */
if (setgid(AID_SHELL) != 0) {
exit(1);
}
if (setuid(AID_SHELL) != 0) {
exit(1);
}
/* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
cap.inheritable = 0;
capset(&header, &cap);
D("Local port disabled\n");
} else {
char local_name;
build_local_name(local_name, sizeof(local_name), server_port);
if(install_listener(local_name, "*smartsocket*", NULL)) {
exit(1);
}
}
}
页:
[1]