元始天尊 发表于 2016-5-10 20:01:43

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]
查看完整版本: adb root/adb reboot/adb remount实现简易剖析