Android LocalSocket client can't connect to native service socket in abstract namespace

4.1k views Asked by At

I'm wrapping libril library and trying to open a socket from there. Trying to open socket in /dev/socket fails since rild is running as user 'radio' and it has no permission, opening a socket in the abstract namespace seems ok however the client (android app) is getting "Permission denied" when trying to connect. I made a test client and server under plain Linux and both processes get connected even when one is ran as root and the other as low privilege user in a different group.

Any ideas how to get this working on the phone? I polished the code in the part bind and connect and I'm giving the proper length. Note that when the socket is not configured properly or the length is incorrect on the server or client side the error is "Connection refused". Now I get 'Permission denied'. I'll appreciate all the help, including ideas how to make the communication by other means.

Server:

#define SOCKET_ADDR "test.socket"
void* initSRV(void* dummy) {
    int err       =  0;
    int fdListen  = -1;
    int fdConnect = -1;
    int i;
    char buf[4096];

    struct sockaddr_un sock;
    socklen_t len  = 0;


    memset(&sock, 'x', sizeof(struct sockaddr_un));


    sock.sun_family = AF_UNIX;
    sock.sun_path[0] = '\0';
    strncpy(sock.sun_path+1, SOCKET_ADDR, strlen(SOCKET_ADDR));
    len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(SOCKET_ADDR);

    LOGD("Create socket %s. len=%d", SOCKET_ADDR, len);
    fdListen = socket(AF_UNIX, SOCK_STREAM, 0);

    LOGD("Bind socket %s.", SOCKET_ADDR);
    err = bind(fdListen, (struct sockaddr*)(&sock), len);
    if(0 != err) {
        LOGE("Unable to bind socket errno:%d [%s]", errno, strerror(errno));
    }

    LOGD("Listening on socket %s.", SOCKET_ADDR);
    err = listen(fdListen, 1);
    if(0 != err) {
        LOGE("Unable to listen socket errno:%d [%s]", errno, strerror(errno));
        return(0);
    }

    while(1) {
        LOGD("Accepting connections on socket [%d]%s.", len, SOCKET_ADDR);
        fdConnect = accept(fdListen, (struct sockaddr *) &sock, &len);

        if(0 > fdConnect) {
            LOGE("Error accepting on socket: [%s]\n",strerror(errno));
            return(0);
        }

        while(len = recv(fdConnect, &buf, sizeof(buf), 0), len > 0) {
            //echo back what we received
            send(fdConnect, &buf, len, 0);
        }
    }

    close(fdConnect);
}

Client:

m_socket = new LocalSocket();
m_socket_address = new LocalSocketAddress(SOCKET_NAME, LocalSocketAddress.Namespace.ABSTRACT);

try{
    m_socket.connect(m_socket_address);
} catch (IOException e) {
    m_socket = null;
    m_log.e(e);
}

if(null != m_socket && m_socket.isConnected()) {
    try {
        m_socket.close();
    } catch (IOException e) {
        m_log.e(e);
    } finally {
        m_socket = null;
    }
}

Log:

06-23 22:59:26.631  22681-22716/--- W/System.err? java.io.IOException: Permission denied
06-23 22:59:26.631  22681-22716/--- W/System.err? at android.net.LocalSocketImpl.connectLocal(Native Method)
06-23 22:59:26.631  22681-22716/--- W/System.err? at android.net.LocalSocketImpl.connect(LocalSocketImpl.java:293)
06-23 22:59:26.631  22681-22716/--- W/System.err? at android.net.LocalSocket.connect(LocalSocket.java:130)
1

There are 1 answers

1
Shrivatsa Hande On

Create socket in path /data/data/your.app.package directory where your app has permission

#define SOCKET_ADDR "/data/data/com.my.app.package/test.socket"

Then you will be able to access it