从NDK JNI连接到外部Unix域套接字

时间:2019-10-22 12:35:04

标签: android-ndk java-native-interface unix-socket

我正在构建一个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可执行文件时,它工作得很好,在这里我是否遗漏了一些明显的东西?

1 个答案:

答案 0 :(得分:0)

对于可能关注此问题的任何人,有必要在每次以root身份启动套接字伪文件时对其手动设置适当的权限,否则connect()会失败,并且将errno设置为EACCESS。我尚未找到更好的解决方案。