我正在构建一个POC Android应用程序,该应用程序需要通过与该二进制文件绑定并监听的Unix域套接字服务器与ELF二进制文件进行通信。该应用程序适用于有根电话,并在启动时以超级用户身份执行二进制文件。我需要使用驻留在本机代码中的客户端的二进制文件进行连接,这是我目前无法做到的。
我正在使用libsocket的自移植精简版本来实现二进制文件和Android应用程序的域套接字功能(通过JNI)。二进制文件可以与命令行客户端完美通信,但是,它无法与我在JNI代码中实现的客户端连接。我确保二进制文件正在/data/data/<my_package_name>/files
上运行,并且服务器套接字具有公共访问权限(777)。
在研究上述问题时,我偶然发现了NDK要求LocalSockets必须位于Linux抽象命名空间中的事实。我的服务器(手臂二进制文件)绑定到绝对路径(/data/data/<my_package_name>/files/serversocket
),因为libsocket不支持unix域套接字的抽象名称空间(由于使用了strlen()
和strncopy()
,而它们不支持)支持以\0
开头的字符串。
以下是来自libsocket的create_socket的代码,该代码以fd为负失败。
int create_socket(const char* path, int flags) {
if (path == NULL) {
return -1;
}
if (strlen(path) > sizeof(((struct sockaddr_un*) 0)->sun_path) - 1) {
return -1;
}
int fd = socket(AF_LOCAL, SOCK_STREAM | flags, 0);
if (fd < 0) {
return -1;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_LOCAL;
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
// the connect call below fails, errno is set to 13 (EACCESS)
if (connect(fd, (struct sockaddr*) &addr, sizeof(addr.sun_family) + strlen(addr.sun_path))) {
close(fd);
return -1;
}
return fd;
}
编辑: 在上面的代码中,对connect()的调用失败,将errno设置为13(EACCESS)。这似乎是特权不足的问题。
我想知道是否有什么方法可以将我的客户端连接到NDK中的绝对路径。当我将客户端打包为以超级用户身份运行的ELF可执行文件时,它工作得很好,在这里我是否遗漏了一些明显的东西?
答案 0 :(得分:0)
对于可能关注此问题的任何人,有必要在每次以root身份启动套接字伪文件时对其手动设置适当的权限,否则connect()
会失败,并且将errno设置为EACCESS。我尚未找到更好的解决方案。