___2017

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、背景

目前,很多嵌入式Linux开发为了调试方便移植了adb到Linux,官方也有相应的patch。作为产品方基于安全考虑,可以在量产时关闭adb;如果需要保留,那么应该在adb登陆系统时验证密码。

 

二、adb登录流程

在使用adb shell命令登陆系统时,adb服务(adbd)为我们fork一个子shell作为终端,源码如下:

// core/adbd/services.c
#define
SHELL_COMMAND "/bin/sh" static int create_subproc_thread(const char *name) { stinfo *sti; adb_thread_t t; int ret_fd; pid_t pid; if(name) { ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); } else { ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); } D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); ....... } static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) { char *devname; int ptm; ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); if(ptm < 0){ printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); return -1; } fcntl(ptm, F_SETFD, FD_CLOEXEC); if(grantpt(ptm) || unlockpt(ptm) || ((devname = (char*) ptsname(ptm)) == 0)){ printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); adb_close(ptm); return -1; } *pid = fork(); if(*pid < 0) { printf("- fork failed: %s -\n", strerror(errno)); adb_close(ptm); return -1; } if(*pid == 0){ int pts; setsid(); pts = unix_open(devname, O_RDWR); if(pts < 0) { fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); exit(-1); } dup2(pts, 0); dup2(pts, 1); dup2(pts, 2); adb_close(pts); adb_close(ptm); // set OOM adjustment to zero char text[64]; snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); int fd = adb_open(text, O_WRONLY); if (fd >= 0) { adb_write(fd, "0", 1); adb_close(fd); } else { D("adb: unable to open %s\n", text); } execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { // Don't set child's OOM adjustment to zero. // Let the child do it itself, as sometimes the parent starts // running before the child has a /proc/pid/oom_adj. // """adb: unable to open /proc/644/oom_adj""" seen in some logs. return ptm; } }

 

三、增加密码验证功能

系统登陆时验证密码是通过/bin/login命令实现的,所以我们只需要fork时执行它既可。

--- b/core/adbd/services.c
+++ b/core/adbd/services.c
-#define SHELL_COMMAND "/bin/sh" 
+#define SHELL_COMMAND "/bin/adb_shell"

bin/adb_shell:可执行脚本:
#!/bin/sh
export ENV='/etc/adb_profile'
if [ $1 = '-' ];then
    /bin/login
elif [ $1 = '-c' ];then
    /bin/login -c "$2"
else
    /bin/login
fi

 

/etc/adb_profile:登陆前需要设置环境变量,这里只是简单的复用/etc/profile里的设置:
#!/bin/sh
. /etc/profile

 

posted on 2019-08-12 20:16  yin'xiang  阅读(7067)  评论(0编辑  收藏  举报